我有一个名为文档的Mongo集合,它具有以下结构:
{
name: "..."
tokens: [
{
_id: <string (unique)>,
tf: <integer>,
tf_idf: <float>
},
...
]
}
我有一份我想保留的令牌列表。是否可以使用$pull
建立查询以删除列表中未包含id的所有令牌?
以下不起作用:
db.documents.update({name: "foo"}, {
$pull : {
$not : {
$elemMatch : { 'tokens' : { '_id' : ['foo', 'bar'] }}
}
}
})
我到目前为止看到的唯一选择是迭代所有文档并检查客户端是否保留令牌并最终逐个删除它们。我宁愿使用一种方法,不涉及将所有数据都拉到客户端只是为了检查哪些令牌可以被删除而哪些不被删除。
答案 0 :(得分:4)
让我们考虑一下这些数据:
> db.nicolas.find()
{ "_id" : ObjectId("4edfd6551757be3330db7c75"),
"tokens" : [ { "id" : 1 }, { "id" : 2 }, { "id" : 3 } ] }
{ "_id" : ObjectId("4edfd50452d5d16ccc1aa7b5"),
"tokens" : [ { "id" : 3 }, { "id" : 4 }, { "id" : 5 } ] }
如果我应用这些转换:
> db.nicolas.update({_id: ObjectId("4edfd6551757be3330db7c75")},
{$pull:{tokens: { id :{$nin:[1,2]}} } })
我会得到以下内容:
> db.nicolas.find()
{ "_id" : ObjectId("4edfd6551757be3330db7c75"),
"tokens" : [ { "id" : 1 }, { "id" : 2 } ] }
{ "_id" : ObjectId("4edfd50452d5d16ccc1aa7b5"),
"tokens" : [ { "id" : 3 }, { "id" : 4 }, { "id" : 5 } ] }
因此,对于您的情况,这样的事情应该有效:
> db.documents.update({name: "foo"},
{$pull: {tokens: { _id : {$nin:['foo','bar']}} } })
有效吗?
答案 1 :(得分:1)
如果我理解正确,你只想保留_id值与“foo”或“bar”匹配的标记,对吗?
鉴于收集:
> db.test.find()
{
"_id" : 1,
"name" : "Doc1",
"tokens" : [
{
"_id" : "foo",
"tf" : 1,
"tf_idf" : 1
},
{
"_id" : "buzz",
"tf" : 2,
"tf_idf" : 2
}
]
},
{
"_id" : 2,
"name" : "Doc2",
"tokens" : [
{
"_id" : "bar",
"tf" : 3,
"tf_idf" : 3
},
{
"_id" : "bing",
"tf" : 4,
"tf_idf" : 4
}
]
}
以下更新应该可以完成您要执行的操作。这将从每个文档的“tokens”数组中删除_id值与“foo”或“bar”匹配的所有子文档。
> db.test.update({}, {$pull:{tokens:{_id:{$nin:["foo", "bar"]}}}}, false, true)
> db.test.find()
{ "_id" : 1, "name" : "Doc1", "tokens" : [ { "_id" : "foo", "tf" : 1, "tf_idf" : 1 } ] }
{ "_id" : 2, "name" : "Doc2", "tokens" : [ { "_id" : "bar", "tf" : 3, "tf_idf" : 3 } ] }
$ pull运算符上的Mongo文档可以在这里找到: http://www.mongodb.org/display/DOCS/Updating#Updating-%24pull
希望这会帮助你做你需要的事情。祝你好运!