簡體   English   中英

查詢父項時如何獲取貓鼬子文檔數組中值的總和?

[英]How to get aggregated sum of values in an array of mongoose subdocuments when query parent?

我正在嘗試在express和mongoose之上構建一些高級的hello world應用程序。 假設我有下一個模式:

const pollOptionsSchema = new Schema({
  name: String,
  votes: {
    type: Number,
    default: 0
  }
});

const pollSchema = new Schema({
  name: String,
  dateCreated: { type: Date, default: Date.now },
  author: { type: Schema.Types.ObjectId },
  options: [pollOptionsSchema]
});

當我簡單地打電話

Poll.findOne({_id: req.params.id}).exec((err, data) => {
  if (err) console.log(err);
  // I receive next data:
  // { _id: 58ef3d2c526ced15688bd1ea,
  //   name: 'Question',
  //   author: 58dcdadfaea29624982e2fc6,
  //   __v: 0,
  //   options:
  //    [ { name: 'stack', _id: 58ef3d2c526ced15688bd1ec, votes: 5 },
  //      { name: 'overflow', _id: 58ef3d2c526ced15688bd1eb, votes: 3 } ],
  //   dateCreated: 2017-04-13T08:56:12.044Z }
});

問題是,在Model級別上調用某些方法后,如何才能獲得相同的數據+投票總數(即上述情況下為8),例如:

  // I want to receive:
  // { _id: 58ef3d2c526ced15688bd1ea,
  //   name: 'Question',
  //   author: 58dcdadfaea29624982e2fc6,
  //   __v: 0,
  //   totalNumberOfVotes: 8,
  //   options:
  //    [ { name: 'stack', _id: 58ef3d2c526ced15688bd1ec, votes: 5 },
  //      { name: 'overflow', _id: 58ef3d2c526ced15688bd1eb, votes: 3 } ],
  //   dateCreated: 2017-04-13T08:56:12.044Z }

還是我需要在文檔級別上實現一些額外的方法,例如(data.aggregate)?

我已經查看過:

  1. http://mongoosejs.com/docs/api.html#model_Model.mapReduce
  2. http://mongoosejs.com/docs/api.html#aggregate_Aggregate
  3. https://docs.mongodb.com/manual/core/map-reduce/
  4. https://docs.mongodb.com/manual/tutorial/map-reduce-examples/

但不能用於我的情況:(

任何建議將不勝感激。 謝謝!

使用$reduce了內操作$addFields管道創建totalNumberOfVotes領域。 在聚合管道中,第一步是$match ,它過濾文檔流,以僅允許匹配的文檔未經修改地傳遞到下一個管道階段,並使用標准MongoDB查詢。

考慮運行以下聚合操作以獲得所需的結果:

Poll.aggregate([
    { "$match": { "_id": mongoose.Types.ObjectId(req.params.id) } },
    {
        "$addFields": {
            "totalNumberOfVotes": {
                "$reduce": {
                    "input": "$options",
                    "initialValue": 0,
                    "in": { "$add" : ["$$value", "$$this.votes"] }
                }
            }
        }
    }
]).exec((err, data) => {  
    if (err) console.log(err);
    console.log(data);
});

注意:以上內容適用於MongoDB 3.4及更高版本。


對於其他早期版本,您需要先$unwind options數組,然后再將非規范化文檔分組到$group管道步驟中,並與累加器$sum$push$first聚合。

以下示例顯示了此方法:

Poll.aggregate([
    { "$match": { "_id": mongoose.Types.ObjectId(req.params.id) } },
    { "$unwind": { "path": "$options", "preserveNullAndEmptyArrays": true } },
    {
        "$group": {
            "_id": "$_id",
            "totalNumberOfVotes": { "$sum": "$options.votes" },
            "options": { "$push": "$options" },
            "name": { "$first": "$name" },
            "dateCreated": { "$first": "$dateCreated" },
            "author": { "$first": "$author" }
        }
    }
]).exec((err, data) => {  
    if (err) console.log(err);
    console.log(data);
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM