MongoDB:查询和检索嵌入式数组中的对象?

时间:2022-09-11 16:10:41

Let's say I have the following document schema in a collection called 'users':

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

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

The 'items' array contains objects in the following format:

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

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

Each user can have multiple items embedded in the 'items' array.

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

Now, I want to be able to fetch an item by an item_id for a given user.

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

For example, I want to get the item with id "1234" that belong to the user with name "John".

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

Can I do this with mongoDB? I'd like to utilize its powerful array indexing, but I'm not sure if you can run queries on embedded arrays and return objects from the array instead of the document that contains it.

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

I know I can fetch users that have a certain item using {users.items.item_id: "1234"}. But I want to fetch the actual item from the array, not the user.

我知道我可以使用{users.items.item_id:“1234”}来获取拥有某个项目的用户。但我想从数组中获取实际项目,而不是用户。

Alternatively, is there maybe a better way to organize this data so that I can easily get what I want? I'm still fairly new to mongodb.

或者,是否有更好的方法来组织这些数据,以便我可以轻松地得到我想要的东西?我仍然是mongodb的新手。

Thanks for any help or advice you can provide.

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

3 个解决方案

#1


24  

The question is old, but the response has changed since the time. With MongoDB >= 2.2, you can do :

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

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

You will have :

你将会拥有 :

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

See Documentation of $elemMatch

请参阅$ elemMatch的文档

#2


6  

There are a couple of things to note about this:

关于此,有几点需要注意:

1) I find that the hardest thing for folks learning MongoDB is UN-learning the relational thinking that they're used to. Your data model looks to be the right one.

1)我发现学习MongoDB的人最难的事情是联合学习他们习惯的关系思维。您的数据模型看起来是正确的。

2) Normally, what you do with MongoDB is return the entire document into the client program, and then search for the portion of the document that you want on the client side using your client programming language.

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

In your example, you'd fetch the entire 'user' document and then iterate through the 'items[]' array on the client side.

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

3) If you want to return just the 'items[]' array, you can do so by using the 'Field Selection' syntax. See http://www.mongodb.org/display/DOCS/Querying#Querying-FieldSelection for details. Unfortunately, it will return the entire 'items[]' array, and not just one element of the array.

3)如果只想返回'items []'数组,可以使用'Field Selection'语法。有关详细信息,请参阅http://www.mongodb.org/display/DOCS/Querying#Querying-FieldSelection。不幸的是,它将返回整个'items []'数组,而不仅仅是数组的一个元素。

4) There is an existing Jira ticket to add this functionality: it is https://jira.mongodb.org/browse/SERVER-828 SERVER-828. It looks like it's been added to the latest 2.1 (development) branch: that means it will be available for production use when release 2.2 ships.

4)现有的Jira票证可以添加此功能:https://jira.mongodb.org/browse/SERVER-828 SERVER-828。看起来它已被添加到最新的2.1(开发)分支中:这意味着它将在2.2版发布时可用于生产。

#3


1  

If this is an embedded array, then you can't retrieve its elements directly. The retrieved document will have form of a user (root document), although not all fields may be filled (depending on your query).

如果这是嵌入式数组,则无法直接检索其元素。检索到的文档将具有用户(根文档)的形式,但并非所有字段都可以填充(取决于您的查询)。

If you want to retrieve just that element, then you have to store it as a separate document in a separate collection. It will have one additional field, user_id (can be part of _id). Then it's trivial to do what you want.

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

A sample document might look like this:

示例文档可能如下所示:

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

Note that this structure ensures uniqueness of item_id per user (I'm not sure you want this or not).

请注意,此结构可确保每个用户的item_id的唯一性(我不确定您是否要这样)。

#1


24  

The question is old, but the response has changed since the time. With MongoDB >= 2.2, you can do :

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

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

You will have :

你将会拥有 :

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

See Documentation of $elemMatch

请参阅$ elemMatch的文档

#2


6  

There are a couple of things to note about this:

关于此,有几点需要注意:

1) I find that the hardest thing for folks learning MongoDB is UN-learning the relational thinking that they're used to. Your data model looks to be the right one.

1)我发现学习MongoDB的人最难的事情是联合学习他们习惯的关系思维。您的数据模型看起来是正确的。

2) Normally, what you do with MongoDB is return the entire document into the client program, and then search for the portion of the document that you want on the client side using your client programming language.

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

In your example, you'd fetch the entire 'user' document and then iterate through the 'items[]' array on the client side.

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

3) If you want to return just the 'items[]' array, you can do so by using the 'Field Selection' syntax. See http://www.mongodb.org/display/DOCS/Querying#Querying-FieldSelection for details. Unfortunately, it will return the entire 'items[]' array, and not just one element of the array.

3)如果只想返回'items []'数组,可以使用'Field Selection'语法。有关详细信息,请参阅http://www.mongodb.org/display/DOCS/Querying#Querying-FieldSelection。不幸的是,它将返回整个'items []'数组,而不仅仅是数组的一个元素。

4) There is an existing Jira ticket to add this functionality: it is https://jira.mongodb.org/browse/SERVER-828 SERVER-828. It looks like it's been added to the latest 2.1 (development) branch: that means it will be available for production use when release 2.2 ships.

4)现有的Jira票证可以添加此功能:https://jira.mongodb.org/browse/SERVER-828 SERVER-828。看起来它已被添加到最新的2.1(开发)分支中:这意味着它将在2.2版发布时可用于生产。

#3


1  

If this is an embedded array, then you can't retrieve its elements directly. The retrieved document will have form of a user (root document), although not all fields may be filled (depending on your query).

如果这是嵌入式数组,则无法直接检索其元素。检索到的文档将具有用户(根文档)的形式,但并非所有字段都可以填充(取决于您的查询)。

If you want to retrieve just that element, then you have to store it as a separate document in a separate collection. It will have one additional field, user_id (can be part of _id). Then it's trivial to do what you want.

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

A sample document might look like this:

示例文档可能如下所示:

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

Note that this structure ensures uniqueness of item_id per user (I'm not sure you want this or not).

请注意,此结构可确保每个用户的item_id的唯一性(我不确定您是否要这样)。