it-swarm.com.ru

MongoDB: сопоставить непустой документ в массиве

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

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

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

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

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

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

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

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

31
Dmitri

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

61
Dmitri

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

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

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

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

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

editied: упс, я пропустил ваш $ elemMatch ...

3
Justin Jenkins

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

1
cwb

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

0
Andreas Jung