Как вытащить вложенные документы, которых нет в данном списке, из коллекции Mongo? - PullRequest
0 голосов
/ 08 декабря 2011

У меня есть коллекция Mongo, называемая документами, которая имеет следующую структуру:

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

У меня есть список токенов, которые я хочу сохранить. Можно ли как-то создать запрос, используя $pull, чтобы удалить все токены, чей идентификатор не содержится в списке?

Не работает следующее:

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

Единственная альтернатива, которую я вижу до сих пор, - это перебирать все документы и проверять на клиенте, сохранять ли токен и в конечном итоге удалять его один за другим. Я бы предпочел использовать подход, который не предполагает передачи всех данных клиенту, просто чтобы проверить, какие токены можно удалить, а какие нет.

Ответы [ 2 ]

4 голосов
/ 08 декабря 2011

давайте рассмотрим эти данные:

> 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 голос
/ 08 декабря 2011

Если я правильно понимаю, вы хотели бы оставить только токены, значение _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 
    }
]
}

Следующее обновление должно выполнить то, что вы хотите сделать. Это удалит все вложенные документы, значение _id которых соответствует «foo» или «bar» из массива «tokens» каждого документа.

> 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 } ] }

Документацию Mongo об операторе $ pull можно найти здесь: http://www.mongodb.org/display/DOCS/Updating#Updating-%24pull

Надеюсь, это поможет вам сделать то, что вам нужно. Удачи!

...