MongoDB: How do I know if an array field contains an element?

I have two collections. The first collection contains students:

{ "_id" : ObjectId("51780f796ec4051a536015cf"), "name" : "John" } { "_id" : ObjectId("51780f796ec4051a536015d0"), "name" : "Sam" } { "_id" : ObjectId("51780f796ec4051a536015d1"), "name" : "Chris" } { "_id" : ObjectId("51780f796ec4051a536015d2"), "name" : "Joe" } 

The second collection contains courses:

 { "_id" : ObjectId("51780fb5c9c41825e3e21fc4"), "name" : "CS 101", "students" : [ ObjectId("51780f796ec4051a536015cf"), ObjectId("51780f796ec4051a536015d0"), ObjectId("51780f796ec4051a536015d2") ] } { "_id" : ObjectId("51780fb5c9c41825e3e21fc5"), "name" : "Literature", "students" : [ ObjectId("51780f796ec4051a536015d0"), ObjectId("51780f796ec4051a536015d0"), ObjectId("51780f796ec4051a536015d2") ] } { "_id" : ObjectId("51780fb5c9c41825e3e21fc6"), "name" : "Physics", "students" : [ ObjectId("51780f796ec4051a536015cf"), ObjectId("51780f796ec4051a536015d0") ] } 

Each course document contains an array of students that contains a list of students registered for the course. When a student views a course on a web page, he needs to see if he is registered for the course or not. To do this, when the courses collection receives a request on behalf of the student, we need to find out if the students array contains the ObjectId student. Is there a way to specify in the projection of the search query to retrieve the student ObjectId from the students array only if there is one?

I tried to figure out if I can use the $ elemMatch operator, but it is oriented towards an array of subdocuments. I understand that I could use the aggregation structure, but it seems that in this case it will be overloaded. The aggregation structure will probably not be as fast as a single search request. Is there a way to request a cursor collection so that the returned document can be in a form like this?

 { "_id" : ObjectId("51780fb5c9c41825e3e21fc4"), "name" : "CS 101", "students" : [ ObjectId("51780f796ec4051a536015d0"), ] } 
+63
mongodb
Apr 24 '13 at 17:26
source share
3 answers

[ change based on this is now possible in recent versions]

[Updated answer] You can request the following method of returning the class name and student ID only if they are already registered.

 db.student.find({}, {_id:0, name:1, students:{$elemMatch:{$eq:ObjectId("51780f796ec4051a536015cf")}}}) 

and you will return what you expected:

 { "name" : "CS 101", "students" : [ ObjectId("51780f796ec4051a536015cf") ] } { "name" : "Literature" } { "name" : "Physics", "students" : [ ObjectId("51780f796ec4051a536015cf") ] } 

[Original answer] It is not possible to do what you want to do at present. This is unfortunate because you could do this if the student were stored in an array as an object. In fact, I'm a little surprised that you only use ObjectId (), as this will always require you to look for students if you want to display a list of students studying at a particular course (first find the Id list, then look at the names in the student collection - two requests instead of one!)

If you stored (as an example) the identifier and name in an array of courses, for example:

 { "_id" : ObjectId("51780fb5c9c41825e3e21fc6"), "name" : "Physics", "students" : [ {id: ObjectId("51780f796ec4051a536015cf"), name: "John"}, {id: ObjectId("51780f796ec4051a536015d0"), name: "Sam"} ] } 

Then your request will be simple:

 db.course.find( { }, { students : { $elemMatch : { id : ObjectId("51780f796ec4051a536015d0"), name : "Sam" } } } ); 

If this student was registered only in CS 101, you will return:

 { "name" : "Literature" } { "name" : "Physics" } { "name" : "CS 101", "students" : [ { "id" : ObjectId("51780f796ec4051a536015cf"), "name" : "John" } ] } 
+61
Apr 25 '13 at 4:54 on
source share

It looks like the $in operator will serve your purpose just fine.

You can do something like this (pseudo query):

 if (db.courses.find({"students" : {"$in" : [studentId]}, "course" : courseId }).count() > 0) { // student is enrolled in class } 

Alternatively, you can remove the sentence "course" : courseId and return the set of all classes in which the student participated.

+21
Apr 24 '13 at 17:31
source share

I try to explain by setting the problem statement and its solution. Hope this helps

Formulation of the problem:

Find all published products whose name, for example, ABC Product or PQR Product, and the price must be below 15 / -

Decision:

Below are the conditions to take care of.

  1. Product price must be less than 15
  2. The product name must be either ABC Product or PQR Product.
  3. Item must be in published condition.

The following is a statement that applies the above criteria to create a query and fetch data.

 $elements = $collection->find( Array( [price] => Array( [$lt] => 15 ), [$or] => Array( [0]=>Array( [product_name]=>Array( [$in]=>Array( [0] => ABC Product, [1]=> PQR Product ) ) ) ), [state]=>Published ) ); 
0
Jun 21 '19 at 10:17
source share



All Articles