【问题标题】:Mongodb:Right way to collect data from two collections?Mongodb:从两个集合中收集数据的正确方法?
【发布时间】:2016-03-17 07:37:19
【问题描述】:

我有两个集合:一个是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")
}

items:

{
    "_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?你能用 MongoDB 3.2 吗?
  • 我使用的是 3.0.6 版本的 MongoDB。我可以切换到 MongoDB 3.2,没有问题

标签: mongodb spring-boot spring-data-mongodb


【解决方案1】:

更新到 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
}

请注意,每增加一个聚合管道阶段,性能就会下降。因此,即使您有一对一的关系,您也可能更喜欢一对多查询。

应用过滤

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

我们必须过滤特定用户和项目类别的数据。所以 user_id 和 category 在 user_item_history 集合中

要过滤您的结果,您应该在查询中添加$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
    }
}])

请注意,“类别”在您的示例数据中被拼错为“类别”,所以我在上面的查询中也不得不拼错。

【讨论】:

  • 感谢您的回答,它对我有用。但我如何在其中添加标准。我还想知道特定用户的项目状态?
  • @Abhisheksaini 使用$match 指定标准。
  • 先生,我需要帮助,我已经更新了问题,所以请使用匹配标准更新您的答案。
  • @Abhisheksaini 我已经更新了我的答案。希望这对你有用。如果您还有其他问题,请将它们作为单独的问题发布,并且不要再修改此问题。
  • 先生,它不工作。现在我没有得到任何结果,即使我也有那个 id 的用户。
猜你喜欢
  • 1970-01-01
  • 2021-07-21
  • 1970-01-01
  • 2019-11-24
  • 2013-04-26
  • 2019-05-11
  • 2017-07-13
  • 1970-01-01
  • 2019-01-13
相关资源
最近更新 更多