如何从 Mongo 集合中$pull 不在给定列表中的嵌入文档?

t6d*_*t6d 0 pull mongodb

我有一个名为文档的 Mongo 集合,它具有以下结构:

{
  name: "..."
  tokens: [
    {
       _id: <string (unique)>,
       tf: <integer>,
       tf_idf: <float>
    },
    ...
  ]
}
Run Code Online (Sandbox Code Playgroud)

我有一个要保留的令牌列表。是否有可能以某种方式建立查询$pull以删除其 id 未包含在列表中的所有令牌?

以下不起作用:

db.documents.update({name: "foo"}, { 
   $pull : { 
       $not : {
           $elemMatch : { 'tokens' : { '_id' : ['foo', 'bar'] }}
       }
   }
})
Run Code Online (Sandbox Code Playgroud)

到目前为止,我看到的唯一替代方法是遍历所有文档并检查客户端是否保留令牌并最终将它们一一删除。我宁愿使用一种不涉及将所有数据拉到客户端的方法,只是为了检查哪些令牌可以删除,哪些不能。

n1r*_*1r3 5

让我们考虑这些数据:

> db.nicolas.find()
{ "_id" : ObjectId("4edfd6551757be3330db7c75"), 
          "tokens" : [ { "id" : 1 }, { "id" : 2 }, { "id" : 3 } ] }
{ "_id" : ObjectId("4edfd50452d5d16ccc1aa7b5"), 
          "tokens" : [ { "id" : 3 }, { "id" : 4 }, { "id" : 5 } ] }
Run Code Online (Sandbox Code Playgroud)

如果我应用这些转换:

> db.nicolas.update({_id: ObjectId("4edfd6551757be3330db7c75")}, 
                    {$pull:{tokens: { id :{$nin:[1,2]}} } })
Run Code Online (Sandbox Code Playgroud)

我会得到以下信息:

> db.nicolas.find()
{ "_id" : ObjectId("4edfd6551757be3330db7c75"), 
          "tokens" : [ { "id" : 1 }, { "id" : 2 } ] }
{ "_id" : ObjectId("4edfd50452d5d16ccc1aa7b5"), 
          "tokens" : [ { "id" : 3 }, { "id" : 4 }, { "id" : 5 } ] }
Run Code Online (Sandbox Code Playgroud)

所以,对于你的情况,这样的事情应该有效:

> db.documents.update({name: "foo"}, 
                      {$pull: {tokens: { _id : {$nin:['foo','bar']}} } }) 
Run Code Online (Sandbox Code Playgroud)

它有效吗?