【问题标题】:Mongoose : associate a .project (aggregation) with .find().limit().sort() etcMongoose:将 .project(聚合)与 .find().limit().sort() 等相关联
【发布时间】:2016-02-28 10:25:58
【问题描述】:

我有一个看起来像这样的猫鼬模式:

var AnswerSchema = new Schema({
  author: {type: Schema.Types.ObjectId, ref: 'User'},
  likes: [{type: Schema.Types.ObjectId, ref: 'User'}],
  date: {type: Date, default: Date.now},
  text: String,
  ....
});

截至目前,我通过以下方式查询此集合:

Answer.find({
    author: profileId,
    date: {$lt: fromDate}
  }).sort({date: -1})
    .limit(25)
    .populate('question.sender', 'username username_display name')
    .exec(function (err, answers) {
        *code here*
    });

但是由于聚合管道,我需要在此查询中添加一个计算字段,以了解访问者是否已经喜欢作者的答案(请参阅this question)。它看起来像这样:

Answer.aggregate()
    .project({
        "author": 1,            
        "matched": {
            "$eq": [ 
                { 
                    "$size": { 
                        "$ifNull": [
                            { "$setIntersection": [ "$likes", [userId] ] }, 
                            []
                        ] 
                    } 
                },
                1
            ]
        }
    })
    .exec(function (err, docs){
        console.log(docs);
    })

问题是:我只需要对由第一个查询过滤的文档运行此投影。换句话说,我需要将 find/limit/sort 与项目结合起来。

我怎么能这样做?我尝试在第一个查询之后(在 .exec() 之前)链接 .project(),但它不起作用。也许我需要通过 mongodb 的聚合链完成我在第一个查询中所做的所有事情?

编辑: 这是一个数据集的例子来试试这个:

{
    "_id" : ObjectId("56334295e45552c018fc475d"),
    "author" : ObjectId("561f9c319cdd94401ae160ef"),
    "likeCount" : 1,
    "likes" : [ 
        ObjectId("561f9c319cdd94401ae160ef")
    ],
    "text" : "This is the answer content",
    "question" : {
        "questionId" : ObjectId("56334031e45552c018fc4757"),
        "sender" : ObjectId("561f9c319cdd94401ae160ef"),
        "date" : ISODate("2015-10-30T10:02:25.323Z")
    },
    "date" : ISODate("2015-10-30T10:12:37.894Z")
},
{
    "_id" : ObjectId("563246cfa04c1b281b6d97bf"),
    "author" : ObjectId("561f9c319cdd94401ae160ef"),
    "likeCount" : 0,
    "likes" : [],
    "text" : "Bla bla bla",
    "question" : {
        "questionId" : ObjectId("562f9a74a16d6fb418752b37"),
        "sender" : ObjectId("561f9c319cdd94401ae160ef"),
        "date" : ISODate("2015-10-27T15:38:28.337Z")
    },
    "date" : ISODate("2015-10-29T16:18:23.020Z")
}

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    project()之前使用聚合流式API的链接方法match()sort() + limit() 方法:

    Answer.aggregate()
        .match({
            "author": profileId,
            "date": { "$lt": fromDate }
        })
        .sort("-date")
        .limit(25)
        .project({
            "author": 1, "question.sender": 1,          
            "matched": {
                "$eq": [ 
                    { 
                        "$size": { 
                            "$ifNull": [
                                { "$setIntersection": [ "$likes", [userId] ] }, 
                                []
                            ] 
                        } 
                    },
                    1
                ]
            }
        })
        .exec(function (err, docs){
            if (err) throw err;
            console.log(docs);
            var answers = docs.map(function(doc) { return new Answer(doc); });
            Answer.populate(answers, { 
                    "path": "question.sender",
                    "select": "username username_display name"
                }, function(err, results) {
                if (err) throw err;
                console.log(JSON.stringify(results, undefined, 4 ));
                res.json(results);
            });         
        });
    

    【讨论】:

    • 仍然缺少一件事: .populate() 似乎不存在。使用聚合 API 时无法调用。
    • @Hexalyse 误解了您问题中的填充要求。我已经用一种可以填充聚合结果的方法更新了我的答案。
    • 谢谢!现在我有一个问题......第一个查询(甚至在填充之前)没有返回任何答案。这很奇怪,因为我之前的查询工作正常。我尝试只放置一个 match(),它没有返回任何文档,所以我认为问题来自 match()。
    • 我在调试聚合管道时通常使用的一个提示是只使用第一个管道运算符运行聚合。如果这给出了预期的结果,请添加下一个。在上面的示例中,您将首先尝试仅使用 .match() 管道进行聚合;如果可行,请添加 sort() 等等。
    • 我添加了一组两个示例文档。测试我的用例应该足够了。
    猜你喜欢
    • 1970-01-01
    • 2020-06-21
    • 2021-05-16
    • 1970-01-01
    • 2018-05-09
    • 2012-03-27
    • 2023-02-10
    • 1970-01-01
    相关资源
    最近更新 更多