Mongodb:从两个集合中收集数据的正确方法?

标签 mongodb spring-boot spring-data-mongodb

我有两个集合:一个是 items,第二个是 user_item_history。我想获取项目及其状态。每个项目的状态存储在 user_item_history 中,项目的其他详细信息位于 items 集合中。我们必须过滤特定用户和项目类别的数据。所以user_id和category在user_item_history集合中。

user_item_history:

{
    "_id" : NumberLong(25424),
    "_class" : "com.samepinch.domain.registration.UserItemHistory",
    "user_id" : NumberLong(25416),
    "item_id" : NumberLong(26220),
    "catagoryPreference" : "BOTH",
    "preference" : 0.6546536707079772,
    "catagory" : "FOOD",
    "status" : 1,
    "createdDate" : ISODate("2015-09-02T07:50:36.760Z"),
    "updatedDate" : ISODate("2015-09-02T07:55:24.105Z")
}

项目:

{
    "_id" : NumberLong(26220),
    "_class" : "com.samepinch.domain.item.Item",
    "itemName" : "Shoes",
    "categoryName" : "SHOPPING",
    "attributes" : [
        "WESTERN",
        "CASUAL",
        "ELEGANT",
        "LATEST"
    ],
    "isAccessed" : false,
    "imageUrl" : "0bd2838e-9349-432a-a200-6e6b659e853eitemcompressed.jpg",
    "catagoryPreference" : "FEMALE",
    "startDate" : ISODate("2015-11-26T18:30:00Z"),
    "endDate" : ISODate("2015-11-27T18:30:00Z"),
    "location" : {
        "coordinates" : [
            77.24149558372778,
            28.56973445677584
        ],
        "type" : "Point",
        "radius" : 2000
    },
    "createdDate" : ISODate("2015-11-16T10:49:11.858Z"),
    "updatedDate" : ISODate("2015-11-16T10:49:11.858Z")
}

作为最终结果,我想要这种格式的文档:

{
    item_id:26220,
    status:1,
    imageUrl: "0bd2838e-9349-432a-a200-6e6b659e853eitemcompressed.jpg"
}

最佳答案

更新到 MongoDB 3.2,您将能够使用 $lookup聚合阶段,其工作原理与 SQL 连接类似。

一对多关系

如果每个 items 文档有许多对应的 user_item_history 文档,您可以以数组形式获取项目状态列表。

查询

db.items.aggregate([
{
    $lookup:
    {
        from: "user_item_history",
        localField: "_id",
        foreignField: "item_id",
        as: "item_history"
    }
},
{
    $project:
    {
        item_id: 1,
        status: "$item_history.status",
        imageUrl: 1
    }
}])

输出示例

{
    "_id" : NumberLong(26220),
    "imageUrl" : "0bd2838e-9349-432a-a200-6e6b659e853eitemcompressed.jpg",
    "status" : [ 1 ]
},
{
    "_id" : NumberLong(26233),
    "imageUrl" : "0bd2838e-9349-432a-a200-6e6b659e853eitemcompressed.jpg",
    "status" : [ 1, 2 ]
}

一对一关系

如果每一项只有一个对应的历史文档,您可以使用以下方法来获取您请求的确切格式:

查询

db.items.aggregate([
{
    $lookup:
    {
        from: "user_item_history",
        localField: "_id",
        foreignField: "item_id",
        as: "item_history"
    }
},
{
    $unwind: "$item_history"
},
{
    $project:
    {
        item_id: 1,
        status: "$item_history.status",
        imageUrl: 1
    }
}])

输出示例

{
    "_id" : NumberLong(26220),
    "imageUrl" : "0bd2838e-9349-432a-a200-6e6b659e853eitemcompressed.jpg",
    "status" : 1
}

请记住,每添加一个额外的聚合管道阶段,性能都会下降。因此,即使您具有一对一关系,您也可能更喜欢一对多查询。

应用过滤

在您的编辑中,您添加了以下内容:

we have to filter data for particular user and category of item. so user_id and category is in user_item_history collection

要过滤结果,您应该添加 $match步骤到您的查询:

db.items.aggregate([
{
    $lookup:
    {
        from: "user_item_history",
        localField: "_id",
        foreignField: "item_id",
        as: "item_history"
    }
},
{
    $unwind: "$item_history"
},
{
    $match:
    {
        "item_history.user_id": NumberLong(25416),
        "item_history.catagory": "FOOD"
    }
},
{
    $project:
    {
        item_id: 1,
        status: "$item_history.status",
        imageUrl: 1
    }
}])

请注意,“category”在您的示例数据中被错误地拼写为“catagory”,因此我也不得不在上面的查询中将其拼写错误。

关于Mongodb:从两个集合中收集数据的正确方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34222712/

相关文章:

mongodb - 如何使用 Spring Data MongoDB 将时间戳投影为 ISODate?

MongoDB > 从嵌套数组中提取集合

node.js - 使用 $group 时是否可以列出不存在的组?

java - Spring Boot 的多重构造函数注入(inject)歧义

javascript - 如何获取header授权

mongodb - 在 MongoRepository<Customer,String> 中使用限制和跳过

geojson - 没有找到适合 GeoJsonPoint 类型的构造函数

mongodb - 去不正确解释http请求

javascript - 确定用户嵌入文档数组中是否存在值

spring - 如何在 Spring-data 中更改/定义 Mongodb 的默认数据库?