MongoDB / Mongoid:搜索与数组中第一项匹配的文档

时间:2013-04-05 22:55:49

标签: ruby-on-rails mongodb mongoid mongoid3

我有一个包含数组的文档:

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

我正在尝试在集合中搜索name数组中第一项的association_chain与给定值匹配的文档。

我怎样才能使用Mongoid?或者,如果您只知道如何使用MongoDB完成此操作,如果您发布示例,那么我可能会想出如何使用Mongoid。

3 个答案:

答案 0 :(得分: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 :(得分: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/

答案 2 :(得分: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")}
}

])