从mongodb数组中提取元素

时间:2018-06-25 02:28:04

标签: node.js mongodb mongoose

我有一个问题,我浪费了更多的时间,而我似乎并没有明白我在做错什么。

我在MongoDB中拥有以下文档:

{
    "personal": {
        ...
    },
    "preferences": {
        ....
    },
    "_id": "5b2efdad564191054807c2b1",
    "pets": [],
    "conversations": [
        {
            "unread": 1,
            "participants": [
                {
                    "_id": "5b2efdcd564191054807c2b2",
                    "name": "Mighty Jules"
                }
            ],
            "messages": [
                {
                    "sender": "self",
                    "timestamp": "2018-06-24T12:29:50.656Z",
                    "_id": "5b2f8ebede342a12a8dcc9d2",
                    "text": "..."
                },
                {
                    "sender": "self",
                    "timestamp": "2018-06-24T12:29:58.022Z",
                    "_id": "5b2f8ec6de342a12a8dcc9d8",
                    "text": "..."
                },
                {
                    "sender": "5b2efdcd564191054807c2b2",
                    "timestamp": "2018-06-24T12:30:27.562Z",
                    "_id": "5b2f8ee3de342a12a8dcc9e5",
                    "text": "..."
                },
                {
                    "sender": "self",
                    "timestamp": "2018-06-24T12:32:48.034Z",
                    "_id": "5b2f8f70d3a83e25bc1abbb2",
                    "text": "..."
                },
                {
                    "sender": "self",
                    "timestamp": "2018-06-24T12:36:20.027Z",
                    "_id": "5b2f9044d4137828283c5a60",
                    "text": "..."
                },
                {
                    "sender": "5b2efdcd564191054807c2b2",
                    "timestamp": "2018-06-24T12:37:39.965Z",
                    "_id": "5b2f90939b4b2a4af8cf50db",
                    "text": "..."
                }
            ],
            "last_message": "2018-06-24T12:37:39.965Z",
            "_id": "5b2efdcd564191054807c2b2"
        },
        {
            "unread": 1,
            "participants": [
                {
                    "_id": "5b300ff657957c1aa0ed0576",
                    "name": "Super Frank"
                }
            ],
            "messages": [
                {
                    "sender": "5b300ff657957c1aa0ed0576",
                    "timestamp": "2018-06-24T21:42:49.392Z",
                    "_id": "5b30105957957c1aa0ed0583",
                    "text": "..."
                }
            ],
            "last_message": "2018-06-24T21:42:49.392Z",
            "_id": "5b300ff657957c1aa0ed0576"
        }
    ],
    "created_date": "2018-06-24T02:10:53.314Z",
    "lastLogin_date": "2018-06-24T02:10:53.314Z",
    "lastUpdate_date": "2018-06-25T02:09:53.281Z",
    "__v": 0
}

我正在尝试使用猫鼬删除几条消息:

const user = await User.findOneAndUpdate(
    {
        _id: mongoose.Types.ObjectId("5b2efdad564191054807c2b1"), //Which is the one that doc
        "conversations._id": mongoose.Types.ObjectId("5b2efdcd564191054807c2b2")
    },
    {
        $pull: {
            "conversations.$.messages": {
                $in: [
                    { _id: mongoose.Types.ObjectId("5b2f9044d4137828283c5a60") },
                    { _id: mongoose.Types.ObjectId("5b2f90939b4b2a4af8cf50db") }
                ]
            }
        }
    },
    {
        new: true,
        projection: {
            conversations: 1
        }
    }
);

在响应中,我得到相同的结果,没有任何内容被删除,没有错误。

2 个答案:

答案 0 :(得分:1)

首先,示例文档中的_id是字符串,而不是ObjectId。 其次,$ pull语法是错误的。请阅读https://docs.mongodb.com/manual/reference/operator/update/pull/#remove-items-from-an-array-of-documents。应该是:

{
    $pull: {
        "conversations.$.messages": { 
            "_id": {
                "$in": ["5b2f9044d4137828283c5a60", "5b2f90939b4b2a4af8cf50db"]
            } 
        }
    }
}

如果需要的话,它将从第一匹配对话中提取消息。如果要从所有匹配的会话中删除邮件,则需要使用$[]代替:"conversations.$[].messages"

答案 1 :(得分:0)

function exists(Arr, objId){
    for(var i = 0; i < Arr.length; i++)
        if(objId.equals(Arr[i]))
            return true    
    return false
}

var user = await User.findOne(
    {_id: mongoose.Types.ObjectId("5b2efdad564191054807c2b1")}
)

for(var j = 0; j<user.conversations.length; j++)
    if(exists([conId],user.conversations[j]._id)
        break

if(j<user.conversations.length)
for(var i =0; i < user.conversations[j].messages.length; i++)
    if(exists(Arr, user.conversations.messages[i]._id))
        delete user.conversations.messages[i]        

user.save()

编辑:仅使用数据库操作

如果要使用$ in,则必须传递整个子数组。

await User.update({_id : "5b2efdad564191054807c2b1", "conversations._id" : "5b2efdcd564191054807c2b2" }, { $pull: { "conversations.$.messages":{ $in : [{"sender" : "self", "timestamp" : "2018-06-24T12:32:48.034Z","_id" : "5b2f8f70d3a83e25bc1abbb2","text" : "..."}] } } }, {multi : true} )

类似$ in的操作将整个文档与数组中的每个元素进行比较。

在您的情况下,它没有找到匹配项,但在该过程中仍然成功,因此没有错误。

如果您只想按ID进行操作,则必须按以下步骤遍历每个ID

for(var i = 0; i < ids.length; i++)
    await User.update({_id : "5b2efdad564191054807c2b1", "conversations._id" : "5b2efdcd564191054807c2b2" }, { $pull: { "conversations.$.messages": {_id : ids[i] } } }, {multi : true} )

或者您知道_id字段,因此可用于搜索$ id

await User.update({_id : "5b2efdad564191054807c2b1", "conversations._id" : "5b2efdcd564191054807c2b2" }, { $pull: { "conversations.$.messages":{ "_id" : { $in : ids } } } }, {multi : true} )