2016-09-27 57 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": "" 
     } 
     } 
    ] 
    } 
} 

我所試圖做的是查詢,將返回只包含約翰·沃森爲用戶的文檔。

在這裏我得到了什麼至今:

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

此查詢將返回唯一的文件3:有到文檔沒有數組和書2不匹配(但我想它返回文檔1和文件3)

2.

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

這一個將返回所有三個文檔:document1和document3是所需的匹配,但查詢也會匹配document2,因爲它在數組中的查詢字段中包含Watson和John,而不管它們是單獨的條目。

有沒有什麼辦法可以做出一個正確的查詢來返回John Watson的document1和document3?

我想在Java中做到這一點,但其他任何示例都可以。

現在我使用兩種查詢結合的解決方法:首先,我使用elementMatch()從查詢中獲得限制(100)結果,然後,如果結果少於100個,則執行第二個查詢並過濾所有錯誤的匹配。但我希望有一個更好,更有效的方法來獲得這些結果。

+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

相關問題