Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose Mongodb querying an array of objects

Tags:

I am struggling to get what I expect to see when querying an array using Mongoose. A user can have many rooms associated with his/her account. The room objects are stored in an array attached to the user within the collection. There is only one collection called users.

Consider the following two Schemas for user and room:

USER SCHEMA

var userSchema = mongoose.Schema({  local            : {     username     : String,     email        : String,     password     : String,     rooms        : {type:Array, default: []} }     }); 

ROOM SCHEMA

var roomSchema = mongoose.Schema({       name: String  }); 

This is the query I have tried:

var User = require('../models/user');  User.find({ 'rooms.name' : req.body.username  },              { rooms:                  { $elemMatch :                     {                       name: req.body.username                     }                  }              }, function (err, user) {          if (err){             return done(err);         }              console.log("user:::", user);          if (user) {             console.log("ROOM NAME FOUND");             req.roomNameAlreadyInUse = true;             next();          } else {             req.roomNameAlreadyInUse = false;             console.log("ROOM NAME NOT FOUND");             next();          }      }); 

The problem is this query seems to always return an empty array even if it should contiain something or if it should return nothing. So how would I search through all users room arrays to see if the room name already exists?

I have also tried the following to queries but neither are successful:

User.find({local: {rooms: {$elemMatch: {name: req.body.username}}}}, function (err,     user) {  }    User.find({'local.rooms': {$elemMatch: {name: req.body.username}}}, function (err, user) {  } 

I should also point out that the database is populated as I can see the array (which has 1 element created on user account creation) in robomongo.

Sample data from console output to show database is being populated (including user.rooms array):

db.users.find() { "_id" : ObjectId("533c4db2b2c311a81be8a256"), "local" : { "password" : "$2a$08$0yQQJ2y0726kZtkWY5mAPOgZhacOmZn0Fd8DlausiuMB XE4ZblTXS", "username" : "paul", "email" : "test", "rooms" : [ { "name" : "paul", "id" : ObjectId("533c4db2b2c311a81be8a2 57") } ], "status" : "active" }, "_v" : 0 } { "_id" : ObjectId("533c4ddab2c311a81be8a258"), "local" : { "password" : "$2a$08$dC3CbDTkG5ozECDTu/IicO3Az0WdkzlGh2xDcb8j1CF/ FQhe5guZq", "username" : "john", "email" : "test2", "rooms" : [ { "name" : "john", "id" : ObjectId("533c4ddab2c311a81be8a 259") } ], "status" : "active" }, "_v" : 0 }

like image 264
Paulie Avatar asked Apr 02 '14 08:04

Paulie


People also ask

How do I query an array of objects in MongoDB?

To search the array of object in MongoDB, you can use $elemMatch operator. This operator allows us to search for more than one component from an array object.

How do I create an array in MongoDB query?

ASP.NET Core 3 MVC Application with MongoDB Case 1 − Create array with MongoDB. If you want to create an array of field UserName and do not want the field _id, use the below query. If you want to create an array with field name _id only, use the below query.

Can we use array in MongoDB?

Unlike relational database models, MongoDB documents can have fields which have values as arrays. The prototypical example in almost all MongoDB documentation is a document having a tags field, whose value is an array of strings, such as ["NoSQL", "Ruby", "MongoDB"] .


2 Answers

I changed it to use findOne instead of find and it works now. I am not too sure why this should make a difference. This is the findOne function I used:

User.findOne({'local.rooms': {$elemMatch: {name: req.body.username}}}, function (err, user) {          if (err){             return done(err);         }              if (user) {             console.log("ROOM NAME FOUND");             req.roomNameAlreadyInUse = true;             next();          } else {             req.roomNameAlreadyInUse = false;             console.log("ROOM NAME NOT FOUND");             next();          }      }); 
like image 117
Paulie Avatar answered Sep 29 '22 18:09

Paulie


findOne returns a single document, where find returns a cursor. Once you go through the cursor of find, you are at the end, and there are no more documents.

User.findOne({'local.rooms': {$elemMatch: {name: req.body.username}}}, (err,UserInfo) => {          if (err){             return res.status(400).json({Error:"Something went wrong please try again"})         }              if (UserInfo) {             console.log("ROOM NAME FOUND");             req.roomNameAlreadyInUse = true;             res.json({msg:"Room name found.",userData:UserInfo})          } else {             req.roomNameAlreadyInUse = false;             console.log("ROOM NAME NOT FOUND");             res.json({msg:"Room name not found."})         }      }); 
like image 28
Binu Avatar answered Sep 29 '22 19:09

Binu