2013-04-05 75 views
2

我有一個數組的文檔文件:的MongoDB/Mongoid:搜索匹配的第一個項目陣列

{ 
    _id: ObjectId("515e10784903724d72000003"), 
    association_chain: [ 
     { 
      name: "Product", 
      id: ObjectId("4e1e2cdd9a86652647000003") 
     } 
    ], 
    //... 
} 

我想搜索的集合的文檔,其中第一項中的nameassociation_chain數組與給定值匹配。

我怎樣才能使用Mongoid來做到這一點?或者如果你只知道如何使用MongoDB來完成這項工作,那麼如果你發佈了一個例子,那麼我可能會想出如何使用Mongoid來做到這一點。

回答

2

兩種方法可以做到這一點:

如果你已經知道

1)您只對出現在「association_chain」中的第一個產品名稱感興趣,那麼這是更好的:

db.items.find("association_chain.0.name":"something") 

請注意,這不會返回所有提及所需產品的項目,但只返回那些在「association_chain」數組的第一個位置提及它的項目。

如果你想做到這一點,那麼你就需要一個索引:

db.items.ensureIndex({"association_chain.0.name":1},{background:1}) 

2)如果你正在尋找一個特定的產品,但你不知道其中association_chain的位置出現,那麼這樣做:

使用MongoDB shell,您可以使用'。'來訪問嵌套結構中的任何散列鍵。點算子!請注意,這與密鑰嵌套在記錄中的深度無關(不是很酷嗎?)

您可以哈希像這樣的嵌入式陣列上做一個發現:

db.items.find("association_chain.name":"something") 

這將返回包含在association_array提及任何地方的目標物的集合中的所有記錄。

如果你想這樣做,你應該確保你有一個指標:

db.items.ensureIndex({"association_chain.name":1},{background: 1}) 

請參閱「點表示法」此頁上:http://docs.mongodb.org/manual/core/document/

+0

第二個代碼塊應該是'db.items.ensureIndex',而不是'.find' – 2013-06-16 22:11:23

+0

的確如此 - 感謝您的接受! – Tilo 2013-06-17 16:21:14

1

你可以用聚合框架來做到這一點。在mongo shell中運行一個查詢來展開文檔,以便每個數組元素具有一個文檔(在其他字段中具有重複的數據),然後按id編組和其他所有要包含的字段以及運算符爲$ first的數組。然後,只需包含$ match運算符即可按名稱或mongoid進行過濾。

這裏的第一產品名稱匹配查詢:

db.foo.aggregate([ 
{ $unwind:"$association_chain"  
}, 
{ 
    $group : { 
      "_id" : { 
       "_id" : "$_id", 
       "other" : "$other" 
      }, 
      "association_chain" : { 
       $first : "$association_chain" 
      } 
     } 
}, 
{ $match:{ "association_chain.name":"Product"} 
} 

]) 

下面介紹如何通過mongoid的第一款產品查詢:

db.foo.aggregate([ 
{ $unwind:"$association_chain"  
}, 
{ 
    $group : { 
      "_id" : { 
       "_id" : "$_id", 
       "other" : "$other" 
      }, 
      "association_chain" : { 
       $first : "$association_chain" 
      } 
     } 
}, 
{ $match:{ "association_chain.id":ObjectId("4e1e2cdd9a86652647000007")} 
} 

]) 
+0

使用聚合框架,因爲我的區別提到或使用Dot Notation的簡單查詢是使用Dot Notation將返回包含數組association_chain的所有元素的整個文檔。在Aggregation中使用此查詢將返回僅匹配數組中匹配元素的文檔(第一個),或者您可以以任何您想要的方式轉換文檔。使用最適合您需求的產品。 – AntonioOtero 2013-04-09 15:07:21

5

使用的位置操作。您可以使用.0(而第二個與.1等)查詢數組的第一個元素。

> db.items.insert({association_chain: [{name: 'foo'}, {name: 'bar'}]}) 
> db.items.find({"association_chain.0.name": "foo"}) 
{ "_id" : ObjectId("516348865862b60b7b85d962"), "association_chain" : [ { "name" : "foo" }, { "name" : "bar" } ] } 

你可以看到的位置操作實際上是因爲在第二個元素搜索foo不返回命中......

> db.items.find({"association_chain.1.name": "foo"}) 
> 

...但搜索bar一樣。

> db.items.find({"association_chain.1.name": "bar"}) 
{ "_id" : ObjectId("516348865862b60b7b85d962"), "association_chain" : [ { "name" : "foo" }, { "name" : "bar" } ] } 

你甚至可以指數這一具體領域沒有索引的所有關聯鏈文件的所有名稱:

> db.items.ensureIndex({"association_chain.0.name": 1}) 
> db.items.find({"association_chain.0.name": "foo"}).explain() 
{ 
     "cursor" : "BtreeCursor association_chain.0.name_1", 
     "nscanned" : 1, 
     ... 

} 
> db.items.find({"association_chain.1.name": "foo"}).explain() 
{ 
     "cursor" : "BasicCursor", 
     "nscanned" : 3, 
     ... 
} 
+1

我不知道你可以濫用像這樣的指數。愛它。 – pestilence669 2013-04-10 07:04:38

相關問題