web-dev-qa-db-ja.com

MongoDB:配列内の空でないドキュメントに一致

私はこのように構造化されたコレクションを持っています:

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

少なくとも1つの「スコア」(スコア配列の要素)があり、特定の値が「バー」で空でない「ユーザー」サブドキュメントがあるすべてのドキュメントを検索する必要があります。

これは私が思いついたものです(そしてそれはうまくいくように見えました):

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

しかし、私はこのエラーを受け取ります:

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

これを行う他の方法は?

33
Dmitri

理解した: { 'score.user': { "$gt": {} } }は空でないドキュメントに一致します。

69
Dmitri

私はあなたのスキーマを完全に理解しているとは思いませんが、おそらく最も簡単な方法はscore.userに「空の」値を設定しないことでしょう。

代わりに、意図的にnotコンテンツがない場合、ドキュメントにそのフィールドがありますか?

次に、クエリは次のようになります...

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

つまり、score.barでミアの存在($ exists、 score.userのdocs )を参照してください(値がある場合は存在しますか?)

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