MongoDB:如何查询和检索嵌套数组中的对象?

21

假设我在名为“users”的集合中有以下文档模式:

{
    name: 'John',
    items: [ {}, {}, {}, ... ]
}

'items'数组包含以下格式的对象:

{
    item_id: "1234",
    name: "some item"
}
每个用户可以在“items”数组中嵌入多个项。
现在,我希望能够根据给定用户的item_id获取项。
例如,我想获取id为“1234”的项目,它属于名为“John”的用户。
我能用mongoDB做到这一点吗?我想利用其强大的数组索引,但我不确定是否可以在嵌套的数组上运行查询并从包含它的文档中返回对象。
我知道我可以使用{users.items.item_id:“1234”}来获取具有特定项的用户。但我想从数组中获取实际的项,而不是用户。
或者,也许有更好的方法来组织这些数据,以便我可以轻松地获得所需的内容?我对mongodb还是比较新的。
感谢您提供任何帮助或建议。

你好,@Nebs,能否审核一下已接受的答案并进行更改?因为在较新版本的mongodb中,有一种解决此问题的方法,无需使用两个单独的集合。 - Burak Karakuş
3个回答

34
问题很古老,但是自那时起响应已经发生了变化。通过MongoDB >= 2.2版本,您可以执行以下操作:
db.users.find( { name: "John"}, { items: { $elemMatch: { item_id: "1234" } } })

您将拥有:

{
   name: "John",
   items: 
   [ 
       {
         item_id: "1234",
         name: "some item"
       }
   ]
}

查看 $elemMatch 的文档


2
这是最佳答案,希望OP看到并更改,否则很多人会看着接受的答案认为没有不用两个集合的解决方案。 - Burak Karakuş

7
有几件事情需要注意:
1) 我发现对于学习MongoDB的人来说,最难的事情是要忘记他们所熟悉的关系型思维方式。你的数据模型看起来是正确的。
2) 通常,在MongoDB中,您会将整个文档返回到客户端程序,然后使用客户端编程语言在客户端上搜索所需的文档部分。
在您的示例中,您将获取整个“user”文档,然后在客户端上迭代“items[]”数组。
3) 如果您只想返回“items[]”数组,则可以使用“Field Selection”语法进行操作。有关详细信息,请参见http://www.mongodb.org/display/DOCS/Querying#Querying-FieldSelection。不幸的是,它将返回整个“items[]”数组,而不仅仅是数组的一个元素。
4) 已经有一个现有的Jira票据来添加此功能: 它是https://jira.mongodb.org/browse/SERVER-828 SERVER-828。看起来已经添加到最新的2.1 (开发)分支中: 这意味着当发布2.2版本时,它将可用于生产使用。

1

如果这是一个嵌入式数组,那么您无法直接检索其元素。检索到的文档将采用用户(根文档)的形式,尽管不一定填充所有字段(具体取决于您的查询)。

如果您只想检索该元素,则必须将其存储为单独的文档在单独的集合中。它将有一个额外的字段user_id(可以是_id的一部分)。然后做你想做的事情就很容易了。

一个示例文档可能如下所示:

{
    _id: {user_id: ObjectId, item_id: "1234"},
    name: "some item"
}

请注意,此结构确保每个用户的item_id唯一(我不确定您是否需要此功能)。

2
谢谢你的回答。我本来想避免使用两个集合,但看起来这是唯一的方法。 - nebs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接