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 }
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.
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.
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"] .
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(); } });
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."}) } });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With