【问题标题】:Need to fetch one documents per user nodejs and mongodb需要为每个用户 nodejs 和 mongodb 获取一个文档
【发布时间】:2017-05-16 17:29:31
【问题描述】:

我有以下结构中的文件:-

{
"_id" : ObjectId("585d64f356ec921620c5d7c5"),
"createdAt" : ISODate("2016-12-23T17:54:59.193Z"),
"updatedAt" : ISODate("2016-12-23T17:54:59.193Z"),
"userid" : ObjectId("5850f42b9a8ea0a43c1355b8"),
"destination" : {
    "id" : ObjectId("584fdcf0e6be59514784e9d4"),
    "lineid" : ObjectId("584f8ddd433c5703acf2618f")
},
"source" : {
    "id" : ObjectId("584fdda2e6be59514784e9df"),
    "lineid" : ObjectId("584fdd2fe6be59514784e9d8")
},
"__v" : 0

}

它们是具有相同结构但重复“userid”字段的多个文档。 现在我想获取符合条件的文档,但每个用户只能获取一个文档。我尝试使用“查找”查询、“聚合”和“组”但没有成功。

我能够使用此查询获取记录,但结果数组包含同一用户的多个文档。

    Route.find({
    $and : [ {
        $or : [ {
            'source.lineid' : request.payload.sourcelineid
        }, {
            'destination.lineid' : request.payload.destinationlineid
        }, {
            'source.id' : request.payload.source
        }, {
            'destination.id' : request.payload.destination
        } ]
    }, {
        userid : {
            $ne : request.user._id
        }
    } ]
}).sort({
    createdAt : -1
})
.exec(function(err, sameroutes) {
    if (err) {
        reply(err).code(500);
    } else {
        reply(sameroutes).code(200);
    }
});

【问题讨论】:

    标签: node.js mongodb mongodb-query aggregation-framework


    【解决方案1】:

    使用 aggregate() 方法,您可以对每个用户的文档进行分组,并使用 $first$last 返回字段累加器运算符。

    过滤可以作为初始 使用 $match 的管道阶段,它使用标准 MongoDB 查询。运行以下管道应该会给你想要的结果:

    Route.aggregate([
        {
            "$match": {
                "userid": { "$ne": request.user._id },
                "$or": [
                    { "source.lineid": request.payload.sourcelineid }, 
                    { "destination.lineid" : request.payload.destinationlineid }, 
                    { "source.id" : request.payload.source }, 
                    { "destination.id" : request.payload.destination }
                ]
            }
        },
        { "$sort": { "userid": 1, "createdAt": -1 } },
        {
            "$group": {
                "_id": "$userid",
                "doc_id": { "$first": "$_id" },
                "createdAt": { "$first": "$createdAt" },
                "updatedAt": { "$first": "$updatedAt" },            
                "destination": { "$first": "$destination" },
                "source": { "$first": "$source" }
            }
        }
    ]).exec(function(err, sameroutes) {
        if (err) {
            reply(err).code(500);
        } else {
            reply(sameroutes).code(200);
        }
    });
    

    【讨论】:

    • 你好@chridam 我尝试了同样的方法,但得到了空数组,但数据库中存在匹配的记录。
    • 您是否尝试过仅使用 $match 运算符运行聚合管道?
    • 是的,至少要检查一下。但没有成功。相同的空数组。
    • 那么这意味着您的查询逻辑有缺陷。在上面,您正在查找用户不是指定的用户并且$or 语句中的任何条件为真的文档。这意味着如果没有匹配任何$or 表达式,那么查询将不会返回任何文档,无论"userid": { "$ne": request.user._id } 查询部分是true 还是false
    • 我尝试简化查询只是为了检查 --- Route.aggregate([ { "$match": { $or:[{ userid : { $eq : request.payload.userid } }] } } ]).exec(function(err, sameroutes) { if (err) { reply(err).code(500); } else { reply(sameroutes).code(200); } }); 并获得了成功
    【解决方案2】:

    我尝试运行的聚合查询 99% 正确,但我错过了将来自有效负载的所有 ID 值转换为 ObjectID。所以正确答案是:-

    Route.aggregate([
        {
            "$match": {
                "userid": { "$ne": request.user._id },
                "$or": [
                    { "source.lineid": mongo.ObjectId(request.payload.sourcelineid) }, 
                    { "destination.lineid" : mongo.ObjectId(request.payload.destinationlineid) }, 
                    { "source.id" : mongo.ObjectId(request.payload.source) }, 
                    { "destination.id" : mongo.ObjectId(request.payload.destination) }
                ]
            }
        },
        { "$sort": { "userid": 1, "createdAt": -1 } },
        {
            "$group": {
                "_id": "$userid",
                "doc_id": { "$first": "$_id" },
                "createdAt": { "$first": "$createdAt" },
                "updatedAt": { "$first": "$updatedAt" },            
                "destination": { "$first": "$destination" },
                "source": { "$first": "$source" }
            }
        }
    ]).exec(function(err, sameroutes) {
        if (err) {
            reply(err).code(500);
        } else {
            reply(sameroutes).code(200);
        }
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多