Mongodb:Right 如何从两个集合中收集数据?

Mongodb:Right way to collect data from two collections?

我有两个合集:一个是items,第二个是user_item_history。我想获取具有状态的项目。每个项目的状态存储在 user_item_history 中,项目的其他详细信息在 items 集合中。我们必须为特定用户和项目类别过滤数据。所以 user_id 和类别在 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 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",因此我也不得不在上面的查询中拼错它。