Подтвердить что ты не робот

MongoDB: сопоставление непустого документа в массиве

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

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

Мне нужно найти все документы, в которых есть хотя бы один "счет" (элемент в массиве баллов), который имеет определенное значение "bar" и непустой "под" документ.

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

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

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

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

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

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

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

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

edited: oops Я пропустил $elemMatch, который у вас был...

Ответ 3

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

Ответ 4

Вероятно, вы захотите добавить вспомогательный массив, который отслеживает пользователей в документе 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 на счетчик вместо массива, но выше это более устойчиво.