20

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

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

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

{
    item_id: "1234",
    name: "some item"
}

每个用户可以在“项目”数组中嵌入多个项目。

现在,我希望能够通过 item_id 为给定用户获取项目。

例如,我想获取属于名为“John”的用户的 id 为“1234”的项目。

我可以用 mongoDB 做到这一点吗?我想利用它强大的数组索引,但我不确定您是否可以对嵌入式数组运行查询并从数组而不是包含它的文档返回对象。

我知道我可以使用 {users.items.item_id: "1234"} 获取具有特定项目的用户。但我想从数组中获取实际项目,而不是用户。

或者,是否有更好的方法来组织这些数据,以便我可以轻松获得我想要的东西?我对 mongodb 还是很陌生。

感谢您提供的任何帮助或建议。

4

3 回答 3

33

这个问题很老,但从那时起反应已经发生了变化。使用 MongoDB >= 2.2,您可以:

db.users.find( { name: "John"}, { items: { $elemMatch: { item_id: "1234" } } })

你将会有 :

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

请参阅 $elemMatch 的文档

于 2014-04-12T12:33:00.927 回答
7

有几点需要注意:

1) 我发现对于学习 MongoDB 的人来说,最难的事情就是不去学习他们习惯的关系思维。您的数据模型看起来是正确的。

2)通常,您使用 MongoDB 所做的是将整个文档返回到客户端程序中,然后使用您的客户端编程语言在客户端搜索您想要的文档部分。

在您的示例中,您将获取整个“用户”文档,然后遍历客户端的“项目 []”数组。

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 发布时用于生产。

于 2012-06-22T22:11:39.163 回答
1

如果这是一个嵌入式数组,那么您不能直接检索它的元素。检索到的文档将具有用户形式(根文档),但并非所有字段都可以填写(取决于您的查询)。

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

示例文档可能如下所示:

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

请注意,这种结构确保了item_id每个用户的唯一性(我不确定你是否想要这个)。

于 2012-06-22T16:06:01.157 回答