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

时间:2015-12-11 11:38:51

标签: 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")
}

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"
}

1 个答案:

答案 0 :(得分:2)

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

一对多关系

如果每个user_item_history文档都有许多相应的items文档,则可以将项目状态列表作为数组获取。

查询

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
    }
}])

请注意,“类别”在示例数据中拼错为“catagory”,因此我也不得不在上面的查询中拼错它。