MongoDB: сопоставить непустой документ в массиве - PullRequest
32 голосов
/ 07 июля 2011

У меня есть коллекция, структурированная таким образом:

{
  _id: 1,
  score: [
    {
      foo: 'a',
      bar: 0,
      user: {user1: 0, user2: 7}
    }
  ]
}

Мне нужно найти все документы, которые имеют хотя бы один «счет» (элемент в массиве оценок), который имеет определенное значение «бар» инепустой вложенный документ 'user'.

Это то, что я придумал (и казалось, что оно должно работать):

db.col.find({score: {"$elemMatch": {bar:0, user: {"$not":{}} }}})

Но я получаю эту ошибку:

error: { "$err" : "$not cannot be empty", "code" : 13030 }

Есть ли другой способ сделать это?

Ответы [ 4 ]

66 голосов
/ 27 июля 2011

Разобрался: { 'score.user': { "$gt": {} } } будет соответствовать непустым документам.

3 голосов
/ 07 июля 2011

Я не уверен, что полностью понимаю вашу схему, но, возможно, самым простым способом было бы не иметь «пустое» значение для score.user ?

Вместо намеренно не есть это поле в вашем документе, если в нем нет содержимого?

Тогда ваш запрос может быть что-то вроде ...

> db.test.find({ "score" : { "$elemMatch" : { bar : 0, "user" : {"$exists": true }}}})

т.е. ищем значение в score.bar , которое вы хотите (0 в данном случае) проверять на наличие существования ($ существующие, см. документы ) score.user (а если оно имеет значение, то оно будет существовать?)

отредактировано : упс, я пропустил $ elemMatch, который у вас был ...

1 голос
/ 07 июля 2011

Возможно, вы захотите добавить вспомогательный массив, который отслеживает пользователей в документе user:

{
  _id: 1,
  score: [
    {
      foo: 'a',
      bar: 0,
      users: ["user1", "user2"],
      user: {user1: 0, user2: 7}
    }
  ]
}

Затем вы можете добавлять новых пользователей атомарно:

> db.test.update({_id: 1, score: { $elemMatch: {bar: 0}}},                       
... {$set: {'score.$.user.user3': 10}, $addToSet: {'score.$.users': "user3"}})

Удалить пользователей:

> db.test.update({_id: 1, score: { $elemMatch: {bar: 0}}},
... {$unset: {'score.$.user.user3': 1}, $pop: {'score.$.users': "user3"}})      

Оценка запросов:

> db.test.find({_id: 1, score: {$elemMatch: {bar: 0, users: {$not: {$size: 0}}}}})

Если вы знаете, что будете добавлять только несуществующих пользователей и удалять существующих пользователей из документа user, вы можете упростить users до счетчика, а не массива, но приведенный выше более устойчив.

0 голосов
/ 07 июля 2011

Посмотрите на оператор $ size для проверки размеров массива.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...