简体   繁体   中英

Mongoose Find not filtering for object property inside array (MongoDB 4.4.1)

I've been trying to make a chat app and I use the following schema for messages:


const messageObject = {
    sender:  {type: mongoose.Schema.Types.ObjectId, ref: 'User', require: true},
    message: {type: String, require: true, min: 1, max: global.messageMaxLength},
    time: Number,
    seen: Boolean
}
const MessageSchema = mongoose.Schema({
    _id: {type: mongoose.Schema.Types.ObjectId, ref: 'User', require: true},
    messages: [messageObject]
}, {versionKey: false}) ;

module.exports = mongoose.model('Messages', MessageSchema);

It takes in entries successfully. Example of entries:

 "_id": "5fb3d971e6092d2da001bbad",
        "messages": [
            {
                "_id": "5fc58bfe0e0ffb313c27fa0a",
                "message": "Hello user",
                "time": 1606781949959,
                "seen": false
            },
            {
                "_id": "5fc58c010e0ffb313c27fa0b",
                "message": "Hello user",
                "time": 1606781953442,
                "seen": false
            },
            {
                "_id": "5fc58c020e0ffb313c27fa0c",
                "message": "Hello user",
                "time": 1606781954137,
                "seen": false
            }
        ]
    }

I want only the seen:false messages now, but when I try to code that in find, or aggregate, I get all the data, ie, the above records:

MessageModel.find({$and: [{_id: req.userData.userid}, {'messages.seen': false}]}).then(result => {
        res.status(200).json({
            message: "passed",
            result,
        });
    })

It however works fine and returns [] if I give {"messages.seen": null}} , and 1 entry with seen: null will return an entire array.

Ive seen all forums there's no place where anybody has encountered this kind of error. Please help.

Thanks

Your message objects are nested inside a document and Mongo will only return either the full document or specific top level fields you have projected. Mongo will not filter out objects within a nested array (as is the case with your schema). So if any of the message objects within the array match the selector, the whole document itself passes the match and returns as a result.

Your options are to either:

  1. Filter out the true/false messages within your code
  2. Change your db structure so that you have a separate messages collection where each document is a single message. So in your example, the collection would look like:
            {
                "_id": "5fc58bfe0e0ffb313c27fa0a",
                "parentId": "5fb3d971e6092d2da001bbad",
                "message": "Hello user",
                "time": 1606781949959,
                "seen": false
            },
            {
                "_id": "5fc58c010e0ffb313c27fa0b",
                "parentId": "5fb3d971e6092d2da001bbad",
                "message": "Hello user",
                "time": 1606781953442,
                "seen": false
            },
            {
                "_id": "5fc58c020e0ffb313c27fa0c",
                "parentId": "5fb3d971e6092d2da001bbad",
                "message": "Hello user",
                "time": 1606781954137,
                "seen": false
            }

And then you can query that collection with:

{ "parentId": "5fb3d971e6092d2da001bbad","seen": false}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM