make a join like SQL server in MongoDB - mongodb

For example, we have two collections
users {userId, firstName, lastName}
votes {userId, voteDate}
I need a report of the name of all users which have more than 20 votes a day.
How can I write query to get data from MongoDB?

The easiest way to do this is to cache the number of votes for each user in the user documents. Then you can get the answer with a single query.
If you don't want to do that, the map-reduce the results into a results collection, and query that collection. You can then run incremental map-reduces that only calculate new votes to keep your results up to date: http://www.mongodb.org/display/DOCS/MapReduce#MapReduce-IncrementalMapreduce

You shouldn't really be trying to do joins with Mongo. If you are you've designed your schema in a relational manner.
In this instance I would store the vote as an embedded document on the user.
In some scenarios using embedded documents isn't feasible, and in that situation I would do two database queries and join the results at the client rather than using MapReduce.

I can't provide a fuller answer now, but you should be able to achieve this using MapReduce. The Map step would return the userIds of the users who have more than 20 votes, the reduce step would return the firstName and lastName, I think...have a look here.

Related

Many to many relations MongoDB

I'm trying to create a database using MongoDB. Since I have no experience with NoSQL database I'm having some troubles with designing the database.
I want to make a database where one student can be part of multiple sessions, and one session can contain multiple students (many-to-many). Also, each event is linked to one student inside one session.
So far I designed it like this:
Sessions:
Sessions.students = [student_id1, student_id2]
Student:
Students.sessions = [session_id1, session_id2]
But my problem is, where should I store the relation, in sessions or in student, or in both (like above)?
And is this the correct way to create the event relationships?
Event:
Event.studentid = [student_id1]
Event.sessionid = [session_id1]
1) If you need to find how many students are in each session and how many sessions each student attends.
For Many-Many relations in mongodb store id's in each other collections.
2) if one of the questions is relevant for your project then only store ids accordingly.
ex: if you need to find session information not student information then store
session.student=[studentid1, id2 id3]; student.session=[] not required
Can also use indexing for searching but dont use too much of it.
As a user you have 2 collections in the database called, students & sessions.
In students collection: each document contains an array of sessionIds & in sessions collection: each document contains array of studentIds.
To get data in list you need to use aggregation
Query for students like
students.aggregate({
//here write query using $match, $unwind, $lookup
//$unwind : sessionIds from sessions
})
Query for sessions like
sessions({
//here write query using $match, $unwind, $lookup
//$unwind : studentIds from students
})

Querying MongoDB: retreive shops by name and by location with one single query

QUERYING MONGODB: RETREIVE SHOPS BY NAME AND BY LOCATION WITH ONE SINGLE QUERY
Hi folks!
I'm building a "search shops" application using MEAN Stack.
I store shops documents in MongoDB "location" collection like this:
{
_id: .....
name: ...//shop name
location : //...GEOJson
}
UI provides to the users one single input for shops searching. Basically, I would perform one single query to retrieve in the same results array:
All shops near the user (eventually limit to x)
All shops named "like" the input value
On logical side, I think this is a "$or like" query
Based on this answer
Using full text search with geospatial index on Mongodb
probably assign two special indexes (2dsphere and full text) to the collection is not the right manner to achieve this, anyway I think this is a different case just because I really don't want to apply sequential filter to results, "simply" want to retreive data with 2 distinct criteria.
If I should set indexes on my collection, of course the approach is to perform two distinct queries with two distinct mehtods ($near for locations and $text for name), and then merge the results with some server side logic to remove duplicate documents and sort them in some useful way for user experience, but I'm still wondering if exists a method to achieve this result with one single query.
So, the question is: is it possible or this kind of approach is out of MongoDB purpose?
Hope this is clear and hope that someone can teach something today!
Thanks

Query moongoDB from a redis list

If for example I keep lists of user posts in redis, for example a user has 1000 posts, and the posts documents are stored into mongodb but the link between the user and the posts is stored inside redis, I can rtetrieve the array containing all the ids of a user post from redis, but what is the efficient way to retrieving them from mongodb?
do I pass a parameter to mongoDB with the array of ids, and mongo will fetch those for me?
I don't seem to find any documentation on this, if Anyone is willing to help me out!
thanks in advance!
To retrieve a number of documents per id, you can use the $in operator to build the MongoDB query. See the following section from the documentation:
http://docs.mongodb.org/manual/reference/operator/query/in/#op._S_in
For instance you can build a query such as:
db.mycollection.find( { _id : { $in: [ id1, id2, id3, .... ] } } )
Depending on how much ids will be returned by Redis, you may have to group them in batch of n items (n=100 for instance) to run several MongoDB queries. IMO, this is a bad practice to build such query containing more than a few thousands ids. It is better to have smaller queries but accept to pay for the extra roundtrips.

How to get result from 2 documents in Mongodb

As we already known as we don't have table joins in Mongodb but if we want to get result from 2 different documents than how we can query to Mongodb? Consider following example.
Document 1 - > department
{Id_:123,name:technical,location:"B Wing"}
{Id_:234,name:account,location:"main Wing"}
{Id_:547,name:HR,location"C Wing"}
Document 2 - > employee
{Id_:a101,name:Peter,dept_id:234,DOB:2010-01-01}
{Id_:a102,name:Liomo,dept_id:547,DOB:1950-01-01}
{Id_:a103,name:Juno,dept_id:123,DOB:1990-01-01}
{Id_:a104,name:ole,dept_id:554,DOB:2011-01-01}
So how can we get all fields like (EmployeeName, DepatmentName, DOB) in one result, I am not getting any way please help me out
Thanks in advance
There is no way. Mongodb does not support joins. The NoSQL way is to denormalize your data, meaning you embed a copy in A of the fields from B you need in A.
There is such a thing as database references, but all that does is provide syntactic sugar for combining the result of two queries client side.
By the way, if your data is really relational in nature (like an employee database the way I would probably design it), perhaps a relational database would be a better fit.

Mongoid: retrieving documents whose _id exists in another collection

I am trying to fetch the documents from a collection based on the existence of a reference to these documents in another collection.
Let's say I have two collections Users and Courses and the models look like this:
User: {_id, name}
Course: {_id, name, user_id}
Note: this just a hypothetical example and not actual use case. So let's assume that duplicates are fine in the name field of Course. Let's thin Course as CourseRegistrations.
Here, I am maintaining a reference to User in the Course with the user_id holding the _Id of User. And note that its stored as a string.
Now I want to retrieve all users who are registered to a particular set of courses.
I know that it can be done with two queries. That is first run a query and get the users_id field from the Course collection for the set of courses. Then query the User collection by using $in and the user ids retrieved in the previous query. But this may not be good if the number of documents are in tens of thousands or more.
Is there a better way to do this in just one query?
What you are saying is a typical sql join. But thats not possible in mongodb. As you suggested already you can do that in 2 different queries.
There is one more way to handle it. Its not exactly a solution, but the valid workaround in NonSql databases. That is to store most frequently accessed fields inside the same collection.
You can store the some of the user collection fields, inside the course collection as embedded field.
Course : {
_id : 'xx',
name: 'yy'
user:{
fname : 'r',
lname :'v',
pic: 's'
}
}
This is a good approach if the subset of fields you intend to retrieve from user collection is less. You might be wondering the redundant user data stored in course collection, but that's exactly what makes mongodb powerful. Its a one time insert but your queries will be lot faster.