的MongoDB/Mongoid:搜索匹配的第一个项目阵列

问题描述:

我有一个数组的文档文件:的MongoDB/Mongoid:搜索匹配的第一个项目阵列

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

我想搜索的集合的文档,其中第一项中的nameassociation_chain数组与给定值匹配。

我怎样才能使用Mongoid来做到这一点?或者如果你只知道如何使用MongoDB来完成这项工作,那么如果你发布了一个例子,那么我可能会想出如何使用Mongoid来做到这一点。

两种方法可以做到这一点:

如果你已经知道

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

你可以用聚合框架来做到这一点。在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

使用的位置操作。您可以使用.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