1

我有一个集合,其中每个对象都包含用户的详细信息以及用户对特定产品的评论,如下所示

{
"_id" : ObjectId("51efcbc8786df13540e46887"),
"value": {
    "UserDetails" : [
                        [
                            {
                                "country" : "CA",
                                "gender" : "M",
                                "age" : "18",
                                "userIdtemp" : ObjectId("51efcbc8786df13540e46887")
                            }
                        ]
                    ],
    "comments" :    [
                        {
                            "commentId" : ObjectId("51efcc41786df13540e46891"),
                            "comment" : "Hey, what's up?",
                            "created" : ISODate("2013-07-24T12:44:49.400Z"),
                            "productId" : ObjectId("51efcbd4786df13540e4688c"),
                            "userId" : ObjectId("51efcbc8786df13540e46887")
                        },
                        {
                            "commentId" : ObjectId("51efcc43786df13540e46893"),
                            "comment" : "Cool",
                            "created" : ISODate("2013-07-24T12:44:51.004Z"),
                            "productId" : ObjectId("51efcbd2786df13540e4688b"),
                            "userId" : ObjectId("51efcbc8786df13540e46887")
                        }
                    ]
    }
}
{
"_id" : ObjectId("51efcbc8786df13540e46888"),
"value" : {
     "UserDetails" : [
                        [
                            {
                               "country" : "US",
                               "gender" : "M",
                               "age" : "25",
                               "userIdtemp" : ObjectId("51efcbc8786df13540e46888")
                            }
                        ]
                ],
     "comments" : [
                    {
                        "commentId" : ObjectId("51efcc41786df13540e46892"),
                        "comment" : "Not much",
                        "created" : ISODate("2013-07-24T12:44:49.475Z"),
                        "productId" : ObjectId("51efcbd4786df13540e4688c"),
                        "userId" : ObjectId("51efcbc8786df13540e46888")
                    }
                ]
}
}
{
    "_id" : ObjectId("51efcbc8786df13540e46889"),
    "value" : {
            "UserDetails" : [
                    {
                            "country" : "US",
                            "gender" : "F",
                            "age" : "13",
                            "userIdtemp" : ObjectId("51efcbc8786df13540e46889")
                    }
            ]
    }
}

我必须与 userDetails 一起单独提取评论,其中 key 为 productId 所以我写了类似以下的地图

mapCommentsFrom = function(){
if("comments" in this.value)
{
    for(var idx = 0;idx<this.value.comments.length;idx++){
        var key = this.value.comments[idx].productId;
        var value = [{
            commentId: this.value.comments[idx].commentId,
            comment:this.value.comments[idx].comment,
            created:this.value.comments[idx].created,
            productId:this.value.comments[idx].productId,
            userId:this.value.comments[idx].userId,
            country:this.value.UserDetails[0][0].country,
            gender:this.value.UserDetails[0][0].gender,
            age : this.value.UserDetails[0][0].age
        }]

    }
}
emit(key,value);
}

reduceFrom = function(k,values){
return values;
}

但是,如果评论的数量不止一个,我只会得到最后一条评论以及用户详细信息和其他人的密钥以及价值为空。像这样的东西

{ "_id" : null, "value" : null }
{
    "_id" : ObjectId("51efcbd2786df13540e4688b"),
    "value" : [
            {
                    "length" : 2,
                    "commentId" : ObjectId("51efcc43786df13540e46893"),
                    "comment" : "Cool",
                    "created" : ISODate("2013-07-24T12:44:51.004Z"),
                    "productId" : ObjectId("51efcbd2786df13540e4688b"),
                    "userId" : ObjectId("51efcbc8786df13540e46887"),
                    "country" : "CA",
                    "gender" : "M",
                    "age" : "18"
            }
    ]
}
{
    "_id" : ObjectId("51efcbd4786df13540e4688c"),
    "value" : [
            {
                    "length" : 1,
                    "commentId" : ObjectId("51efcc41786df13540e46892"),
                    "comment" : "Not much",
                    "created" : ISODate("2013-07-24T12:44:49.475Z"),
                    "productId" : ObjectId("51efcbd4786df13540e4688c"),
                    "userId" : ObjectId("51efcbc8786df13540e46888"),
                    "country" : "US",
                    "gender" : "M",
                    "age" : "25"
            }
    ]
}

有人可以帮我看看我错过了什么吗?

提前感谢您的帮助

4

3 回答 3

0

由于声誉问题,我无法添加评论。但是您是否考虑过使用聚合框架。

操作员将$unwind很容易地返回一组子文档,并且比使用 map/reduce 更快。

我不确定它是否会完全满足您的需求,但可能会有所帮助。

看看,http://docs.mongodb.org/manual/reference/aggregation/unwind/

于 2013-07-29T10:05:56.487 回答
0

到目前为止,简单的方法就是为此使用聚合框架。聚合框架允许您对数据执行运算符,$match用于执行查询(如find())和其他各种。有关更多信息,请参阅:http: //docs.mongodb.org/manual/core/aggregation/

聚合框架还有一个$unwind功能可以完全满足您的需求。你像这样使用它:

db.collection.aggregate( [
    { $unwind: '$value.comments' },
    { $project: {
        _id: '$value.comments.productId',
        value: 1
    } }
] );

在您的示例文档中,这将返回:

{
    "result" : [
        {
            "_id" : ObjectId("51efcbd4786df13540e4688c"),
            "value" : {
                "UserDetails" : [
                    [
                        {
                            "country" : "CA",
                            "gender" : "M",
                            "age" : "18",
                            "userIdtemp" : ObjectId("51efcbc8786df13540e46887")
                        }
                    ]
                ],
                "comments" : {
                    "commentId" : ObjectId("51efcc41786df13540e46891"),
                    "comment" : "Hey, what's up?",
                    "created" : ISODate("2013-07-24T12:44:49.400Z"),
                    "productId" : ObjectId("51efcbd4786df13540e4688c"),
                    "userId" : ObjectId("51efcbc8786df13540e46887")
                }
            }
        },
        {
            "_id" : ObjectId("51efcbd2786df13540e4688b"),
            "value" : {
                "UserDetails" : [
                    [
                        {
                            "country" : "CA",
                            "gender" : "M",
                            "age" : "18",
                            "userIdtemp" : ObjectId("51efcbc8786df13540e46887")
                        }
                    ]
                ],
                "comments" : {
                    "commentId" : ObjectId("51efcc43786df13540e46893"),
                    "comment" : "Cool",
                    "created" : ISODate("2013-07-24T12:44:51.004Z"),
                    "productId" : ObjectId("51efcbd2786df13540e4688b"),
                    "userId" : ObjectId("51efcbc8786df13540e46887")
                }
            }
        },
        {
            "_id" : ObjectId("51efcbd4786df13540e4688c"),
            "value" : {
                "UserDetails" : [
                    [
                        {
                            "country" : "US",
                            "gender" : "M",
                            "age" : "25",
                            "userIdtemp" : ObjectId("51efcbc8786df13540e46888")
                        }
                    ]
                ],
                "comments" : {
                    "commentId" : ObjectId("51efcc41786df13540e46892"),
                    "comment" : "Not much",
                    "created" : ISODate("2013-07-24T12:44:49.475Z"),
                    "productId" : ObjectId("51efcbd4786df13540e4688c"),
                    "userId" : ObjectId("51efcbc8786df13540e46888")
                }
            }
        }
    ],
    "ok" : 1
}
于 2013-07-29T12:28:15.130 回答
0

这是因为您没有在地图功能中发出它们。在 for 循环内移动 emit 函数。

mapCommentsFrom = function(){
if("comments" in this.value){
for(var idx = 0;idx<this.value.comments.length;idx++){
    var key = this.value.comments[idx].productId;
    var value = {
        commentId: this.value.comments[idx].commentId,
        comment:this.value.comments[idx].comment,
        created:this.value.comments[idx].created,
        productId:this.value.comments[idx].productId,
        userId:this.value.comments[idx].userId,
        country:this.value.UserDetails[0][0].country,
        gender:this.value.UserDetails[0][0].gender,
        age : this.value.UserDetails[0][0].age
    }
    emit(key,value);
}
}
}

然后你可能还需要将你的reduce函数重写为这样的东西

reduceFrom = function(k,valueArray){
var returnData = { values : [] } ;
for(var i=0;i<valueArray.length;i++)
    returnData.values.push(valueArray[i]);
return returnData;

}

于 2013-07-29T12:51:36.900 回答