2015-10-15 247 views
3

我的目標是搜索數據的用戶ID的記錄1MongoDB的多嵌套數組搜索

下面是我的數據

{ "_id" : 2, 
    "name" : "test", 
    "data" :[{"_id" : "1","file" : "nic", "userid" : [1,2 ]}, 
      {"_id" : "2","file" : "nic1","userid" : [1 ] }, 
      {"_id" : 3,"file" : "nick2","userid" : [1,2 ]} 
    ]}, 

{ "_id" : 3, 
    "name" : "test", 
    "data" : [{"_id" : "1","file" : "nic","userid" : [1,2 ] }, 
      {"_id" : "2","file" : "nic1", "userid" : [3,2 ] } 
     ]} 

出來放應

{ "_id" : 2, 
    "name" : "test", 
    "data" :[{"_id" : "1","file" : "nic", "userid" : [1,2 ]}, 
      {"_id" : "2","file" : "nic1","userid" : [1 ] }, 
      {"_id" : 3,"file" : "nick2","userid" : [1,2 ]} 
    ]}, 

{ "_id" : 3, 
    "name" : "test", 
    "data" : [{"_id" : "1","file" : "nic","userid" : [1,2 ] },   
     ]} 

我試圖

$res=$collection->find(array("data.userid" =>array('$in'=>array('52')))); 

返回null

回答

1

您需要.aggregate()方法來爲任何數組內容進行「過濾」,而不僅僅是單個匹配,而且基本匹配也非常簡單,因爲MongoDB並不在意數據在數組內,只要指定的路徑是正確的:

db.collection.aggregate([ 
    { "$match": { "data.userid": 1 } }, 
    { "$project": { 
     "data": { 
      "$setDifference": [ 
       { "$map": { 
        "input": "$data", 
        "as": "el", 
        "in": { 
         "$cond": [ 
          { "$setIsSubset": [ [1], "$$el.userid" ] }, 
          "$$el", 
          false 
         ] 
        } 
       }}, 
       [false] 
      ] 
     } 
    }}, 
    { "$match": { "data.0": { "$exists": true } }} 
]) 

在PHP此notates如下:

$collection->aggregate(array(
    array('$match' => array("data.userid" => 1)), 
    array(
     '$project' => array(
      'data' => array(
       '$setDifference' => array(
        array(
         '$map' => array(
          'input' => '$data', 
          'as' => 'el', 
          'in' => array(
           '$cond' => array(
            array('$setIsSubset' => array(array(1),'$$el.userid')), 
            '$$el', 
            FALSE 
           ) 
          ) 
         ) 
        ), 
        array(FALSE) 
       ) 
      ) 
     ) 
    ), 
    array('$match' => array('data.0' => array('$exists' => TRUE))) 
)) 

$map運算符允許外國稅發陣列中的每個元件的檢查,並通過各元件的$cond叔中間操作。這會在「內部」數組上處理$setIsSubset操作,以查看它是否實際上包含備用集中的其中一個值(在此例中爲[1]),並且在其中執行了評估,然後返回元素或以其他方式返回false

$setDifference的目的是從修改後的數組中刪除那些false值,並且只返回匹配的元素。最後,$exists測試看起來看到外部數組實際上至少有一個元素,並且由於過濾而不是空的。

返回的文檔是匹配條件的文檔,只有數組元素也符合指定的條件。

當然,這裏的操作符要求您至少具有MongoDB 2.6作爲服務器(這是一個相當舊的版本,至少是一個建議的更新),但是如果您的版本仍然較少,那麼您需要一個傳統方法$unwind$group

$collection->aggregate(array(
    array('$match' => array("data.userid" => 1)), 
    array('$unwind' => '$data'), 
    array('$match' => array('data.userid' => 1)), 
    array( 
     '$group' => array(
      '_id' => '$_id', 
      'data' => array('$push' => '$data') 
     ) 
    ) 
)) 
+0

收到錯誤'例外:無效操作「$ setDifference'' –

+0

@sasikanth這意味着你有一個相當舊版本的MongoDB(2.6以上),它沒有那些運營商。有一個替代(而不是性能)的方法可以適用於所有版本。 MongoDB 2.6現在已經有幾年了,爲什麼要考慮升級有很多原因。 –

+0

感謝您的幫助。我會更新我的版本並檢查一次。我需要一個更多的幫助。我想顯示數據中的所有記錄作爲循環我怎樣才能做到這一點 –