Mongdb database design - mongodb

I am developing an app and I've chosen mongodb as the database mainly because of its flexibility and the ability to query geospatial data. But I tend to be a bit old school concerning the design (read 'relational database') and I'd like a few hints on how to design my database so it best fits my need.
I have a User model , and let's say a Object item. Each user has a location (which can change rapidly over the time). The Object items also have a location and belongs to a User.
For now I kinda developed my database like I'd do it in MySql:
* A User table with an array of Object ID
* an Object table with a reference to the owner (user) ID.
Since I will need to make frequent query on the location of each model and make some range query (which objects are closer than 100m to this user etc), is this a good design ? My main concern is the location query. I know I can put an index on the location, but I did not want to put two index location on the User and the Object array of the user on the same table.
Another feature is that I will surely be doing some sharding on my database, and according from what I read on mongodb, I think I'll make the sharding on the location index (mostly the user).
Does that make sense or should I actually just go with the one-size-fits-all approach ? Or do you have another design in mind that would be better ?
Thanks.

As per my opinion:
Step 1: You can use three different collections. First one for the Users and second will be Locations and last will be ITEMS(Along with user ID).
Step 2: In your location collection you can save both of the coordinates of the location distinguished by two different types. For example, for user location you can set type as "USER_LOC" and for Object(Item) location you can set type as "ITEM_LOC" along with USER ID and ITEM ID ().
Step 3: As if ITEM and USERS locations are moving so you can save both the(user and item) coordinates in your location collection.
Step 4: You can save last coordinates of item and users in their respective collections itself.
Step: 5 As per your query if you want to fetch items which are near to user in X meter distance so you can filter location collection for ITEM type only and you have last coordinates of the user in USER collection itself. So you can find List of items which are near to user current location within a specific distance.
This is just my opinion. Thanks.

Related

How to store locations in ArangoDB?

I am building a web application where I need to store a large number of unique addresses as nodes in ArangoDB.
One approach would be using a hierarchical graph model: a country node connected to county nodes, county nodes connected to cities and cities connected to exact addresses with GeoJSON attributes.
The other option would be having only address nodes which contain city, county and country as attributes.
Which method would be more beneficial? I would be running queries to find locations in a given range or locations in a given city.
Well, let's see what you will need in terms of collections to build your app:
Collection storing the Places you want to use in your app. This would be your main collection and would contain among other things a map location object {longitude: XXX, Latitude YYY}
Because you probably want people to be able to search by city, country, etc.. You need either a collection per Location type (city, country, etc) or a table with all the locations and a "type" flag that indicates the location is city or country, etc....
3.- You need a table that allows you to start at a country and drill down to a particular set of cities (for example). So, you need a table with a from key and a to key
By this point you probably have noticed that we have basically built a hierarchy, which in Arango I would build as at least one Places vertex collection, a Locations vertex collection and a locationContains edge collection. This would allow for really fast lookups and is one of the reasons why graph databases were originally created.
Now note that since Arango is a multi model DB, you can use the graph syntax (I like anonymous graph syntax myself), but you can also use traditional joins whenever needed, which behave very similar to a traditional relational DB.

"Join" multiple Algolia indices?

Is it possible to "join" indices in Algolia to get a merged result?
For example:
If I have two indices : one for 'users', and one for 'events'. Users each have id and name attributes. Events each have date and userId attributes.
How would I go about searching for all users named "bob", and for each user also return the next 5 events associated with them?
Is it possible to "join" them like you would in a relational database? Or do I need to search for users, then iterate through the hits, searching for events for each user? What's the best solution for this type of query here?
Algolia is not designed as a relational database. To get to what you're trying to achieve, you have to transform all your records into "flat" objects (meaning, each object also includes all their linked dependencies).
In your case, what I would do is to add a new key to your user records, named events and have it be an array of events (just like you save them in the events table). This way, you got all the information needed in one call.
Hope that helps,

How to efficiently check database object based on location/proximity to user's location?

I am constructing an app (in XCode) which, in a general sense, displays information to users. The information is stored as individual objects in a database (happens to be a Parse-server hosted by heroku). The user can elect to "see" information that has been created within a set distance from their current location. (The information, when saved to the DB, is saved along with its lat and long based on the location of the user when they initiated the save). I know I can filter the pieces of information by comparing their lat and long to the viewing user's current lat and long and only display those which are close in enough. Roughly/generally:
var currentUserLat = latitude //latitude of user's current location
var infoSet = [Objects] //set of all pulled info from DB
for info in infoSet{
if info.lat-currentUserLat < 3{//arbitrary value
//display the info
}else{
//don't display
}
}
This is set up decently enough, and it works fine. The reason it works fine, though, is because of the small number of entries in the DB at this current time (the app is in development). Under practical usage (ie many users) the DB may be full of information objects (lets say, a thousand). In my opinion, to individually pull and compare the latitude of the information and compare it to the current user's latitude for each and every DB entry would take too long. I know there must be a way to do it in a timely manner (think tinder... they only display profiles of people who are in the near vicinity and it doesn't take that long for them to do so despite millions of profiles) but I do not know what is most efficient. I thought of creating separate sections for different geographical regions in the DB and then only searching those particular section of the DB depending on where the user's current location is, but this seems unsophisticated and would still lead to large amounts of info being pulled. What is the best way to do this?
Per Deploying a Parse Server to Heroku you can Install a MongoDB add-on or another of the Data Stores in the Add-on Category in which you can use Geospatial Indexes and Queries which are specifically intended for this sort of application.
Is there a reason you need to do that sort of checking on the client side? I would suggest sending your coordinates to your server and then having the server query your database with those coordinates and figure out which items to pull based on the given coordinates respectively. Then you can have the server return back to the client side whichever items were "close" to that user
EDIT: reworded

Database modeling with mean.js and mongoose

I am classical developer who is normally developing relational DBs form my web applications.
I want to learn the new way and build an application with mean.js and mongoDB. I used yo generator from the meanjs.org to get started.
When I model my data I always fall back into the classic relational modeling. And I think this is not what the “new way” of app building is all about.
So my question is: What is he best practice to model my data model sample?
My learning sample is an app in which you have a specific given list of music albums (like best 50 Jazz albums of all times) and the user checks in and rate the music.
I have a CRUD module for adding and editing albums the user should listen to. This ends in an ordered list of albums.
I have a CRUD module for users, generated by the yo generator.
A user now can see the list and mark the albums which he already heard. He should be able to give a rating and a comment.
So the question is: where to store the user listenTo info? In the relational world I would introduce a new foreign key table which has a relation from user to album and model the properties like rating and comment in the foreign key table. I don’t think this is how things should work in mongo DB world, does it?
I could add the user listenTo information to each album. I would have a list of users and comments on each album. Then, I need to ensure that if the list is requested, only the information of the current user is present. So I would have to filter on property on a sub-sub-document. Feels strange.
Or, I could copy the album list for each newly created user but then I need to write code that changes the user’s object when I edit the original list.
What would you recommend?
When I think of Data Modeling, I break things down into the following relationships:
1 <--> 1
1 <--> Few/Many (A finite number, say a list of user's phone numbers)
1 <--> Very Many
The general rule of thumb with MongoDB is you should embed wherever possible. So for 1 <--> 1 and 1 <--> Few/Many if the document size is something small, you should embed the collection inside the user document.
It's important to think about the use case here. If we want to track all songs that the user likes or listens to, this could potentially be hundreds or thousands, so we probably want to store this information in a separate collection and contain an indexed reference to the user there.
In the case of tracking if a user listens to the song, I would probably structure it like this in your use case:
{
_id: ObjectID, // The identifier of the document
user_id: ObjectID, // The user who listened to the song
song_id: ObjectID, // The id of the song
count: number, // The number of times the user listened
rating: number, // The number of stars the user rated the song
favorite: boolean, // If the user marked the song as a favorite
last_listened: Date // The last time the user listened
}
With an index on { user_id: 1, song_id: 1 }.
Here is a really good reference on how to approach your problem:
https://docs.mongodb.com/manual/applications/data-models-relationships/

MeteorJS + MongoDB: How should I set up my collections when users can have the same document?

I wasn't quite sure how to word my question in one line, but here's a more in depth description.
I'm building a Meteor app where users can "own" the same document. For example, a user has a list of movies they own, which of course multiple people can own the same movie. There are several ways I've thought of structuring my database/collections for this, but I'm not sure which would be best.
I should also note that the movie info comes from an external API, that I'm currently storing into my own database as people find them in my app to speed up the next lookup.
Option 1 (My current config):
One collection (Movies) that stores all the movies and their info. Another collection that basically stores a list of movie ids in each document based on userId. On startup, I get the list of ids, find the movies in my database, and store them in local collections (there are 3 of them). The benefit that I see from this is I only have to store the movie once. The downside that I've ran into so far is difficulty in keeping things in sync and properly loading on startup (waiting on the local collections to populate).
Option 2 :
A Movies collection that stores a list of movie objects for each user. This makes the initial lookup and updating very simple, but it means I'll be storing the same fairly large documents multiple times.
Option 3:
A Movies collection with an array of userids on each movie that own that movie. This sounds pretty good too, but when I update the movie with new info, will an upsert work and keep the userids safe?
Option 3 seems sensible. Some of the choice may depend on the scale of each collection or the amount of links (will many users own the same movie, will users own many movies).
Some helpful code snippits for using option 3:
Upsert a movie detail (does not affect any other fields on the document if it already exists):
Movies.upsert({name: "Jaws"}, {$set: {year: 1975}});
Set that a user owns a movie (also does not affect any other document fields. $addToSet will not add the value twice if it is already in the array while using $push instead would create duplicates):
Movies.update({_id: ~~some movie id~~}, {$addToSet: {userIds: ~~some user id~~}});
Set that a user no longer owns a movie:
Movies.update({_id: ~~some movie id~~}, {$pull: {userIds: ~~some user id~~}});
Find all movies that a user owns (mongo automatically searches the field's array value):
Movies.find({userIds: ~~some user id~~});
Find all movies that a user owns, but exclude the users field from the result (keep the document small in the case that movie.userIds is a large array or protect the privacy of other user-movie ownership):
Movies.find({userIds: ~~some user id~~}, {userIds: 0});