2016-09-27 30 views
1

MongoDB QueryBuilderに問題があります。MongoDB単一エントリと配列要素の両方に一致するクエリ

{ 
    "_id": "document1", 
    "data": { 
    "user": { 
     "credentials": { 
     "name": "John", 
     "lastname": "Watson", 
     "middle": "Hemish" 
     } 
    } 
    } 
} 


{ 
    "_id": "document2", 
    "data": { 
    "user": [ 
     { 
     "credentials": { 
      "name": "John", 
      "lastname": "Nicholson", 
      "middle": "Joseph" 
     } 
     }, 
     { 
     "credentials": { 
      "name": "Mary", 
      "lastname": "Watson", 
      "middle": "" 
     } 
     } 
    ] 
    } 
} 


{ 
    "_id": "document3", 
    "data": { 
    "user": [ 
     { 
     "credentials": { 
      "name": "John", 
      "lastname": "Watson", 
      "middle": "Hemish" 
     } 
     }, 
     { 
     "credentials": { 
      "name": "John", 
      "lastname": "Nicholson", 
      "middle": "Joseph" 
     } 
     }, 
     { 
     "credentials": { 
      "name": "Mary", 
      "lastname": "Watson", 
      "middle": "" 
     } 
     } 
    ] 
    } 
} 

私は何をしようとしていますが、ユーザーとしてのジョン・ワトソンを含むドキュメントのみが返されますクエリは、次のとおりです。

は、私は1人以上のユーザーを含めることができる文書の数を、持っていると仮定します。私がこれまでに得たものをここで

:文書1には、アレイと文書2での一致がない(しかし、私はそれをしたいと思います:

1.

QueryBuilder qb = QueryBuilder.start("credentials.lastname").is("Watson").and("credentials.name").is("John"); 
DBObject query = QueryBuilder.start("data.user").elemMatch(qb.get()).get(); 

このクエリのみdocument3を返します。文書1とdocument3)

2.

を戻します

これは3つのドキュメントすべてを返します:document1とdocument3が一致することが望ましいですが、クエリはWatsonとJohnが配列内のクエリフィールドにあるのでdocument2と同様に一致します。

John Watsonに対してdocument1とdocument3が返される正しいクエリを作成する方法はありますか?

私はJavaでそれをやろうとしていますが、他の例であれば問題ありません。

私はelementMatch()でクエリからlimit(100)の結果を取得し、結果が100件未満の場合は2番目のクエリを実行してすべてをフィルタリングします間違った一致。しかし、私はその結果を得るためのより良い、より効果的な方法があることを願っています。

+0

あなたは、クエリビルダフォームに集計クエリを変換できますか? – manetsus

+0

少なくとも私はこれを試すことができます、ありがとう! – yggdraa

+0

ありがとうございました:) – manetsus

答えて

1

userは、キーdataのアンワインド値として配列に格納されます。私はもう少し努力すれば、あなたが望むように正確なフォーマットに導くだろうと思う。

私はそれが目的に役立つはずだと思うように、それを共有しています。それはあなたに役立つはずです。

集計クエリ

db.tuttut.aggregate([ 
    {$unwind:"$data.user"}, 
    { $project: { 
     _id:1, 
     data:1, 
     temp: {name:"$data.user.credentials.name", 
       lastname:"$data.user.credentials.lastname"} 
     } } , 
    { $group:{ 
     _id:"$_id" , 
     data: {$addToSet: "$data"} , 
     temp:{ $addToSet: "$temp" } } }, 
    { $match:{ temp:{name:"John",lastname:"Watson"} } } , 
    {$project:{_id:1, data:1}} 
]).pretty() 

返される結果:

{ 
     "_id" : "document1", 
     "data" : [ 
       { 
         "user" : { 
           "credentials" : { 
             "name" : "John", 
             "lastname" : "Watson", 
             "middle" : "Hemish" 
           } 
         } 
       } 
     ] 
} 
{ 
     "_id" : "document3", 
     "data" : [ 
       { 
         "user" : { 
           "credentials" : { 
             "name" : "John", 
             "lastname" : "Watson", 
             "middle" : "Hemish" 
           } 
         } 
       }, 
       { 
         "user" : { 
           "credentials" : { 
             "name" : "Mary", 
             "lastname" : "Watson", 
             "middle" : "" 
           } 
         } 
       }, 
       { 
         "user" : { 
           "credentials" : { 
             "name" : "John", 
             "lastname" : "Nicholson", 
             "middle" : "Joseph" 
           } 
         } 
       } 
     ] 
} 
+0

ありがとう、私はこれを試してみましょう! – yggdraa

+0

@yggdraaありがとう、申し訳ありませんが、私はあなたに正確なフォーマットを教えてくれませんでした。 – manetsus

+0

まあ、私はそれを試して、 '$グループのメモリ制限を超過しましたが、外部の並べ替えを許可していませんでした。 AllowDiskUse:trueを指定すると受け入れることができます。 '' allowDiskUseでtrue:処理に時間がかかりすぎます(データベースのサイズは〜300Gbですが、これらの名前フィールドはインデックスされますが、いくつかのフィールドのインデックスを作成する必要がありますか?) クエリの最後に$ limit:100) – yggdraa

関連する問題