【问题标题】:mogoose aggregate lookup on the field of object unwind not working对象展开字段上的猫鼬聚合查找不起作用
【发布时间】:2019-12-02 08:02:33
【问题描述】:

我正在尝试从问题文档中查找,同时显示一些用户的结果。用户模式中有一个名为 questionAnswer 的字段,类型为数组。我也正在取消数组字段,但只恢复问题但回答字段。我做错了什么请指导我。

这是我的用户架构:-

let userSchema =  new Schema({
    name: {
        type: String
        required: true
    }
    phoneNo: {
        type: String
        required: true
    }
    questionAnswer: {
        type: [questionAnswerSchema]
    }
});

这是我的问题AnswerSchema

let questionAnswerSchema = new Schema({
    question: {
        type: Schema.Types.ObjectId,
        ref: 'Question',
        required: true
    },
    answer: {
        type: String,
        required: true
    },
});

我的问题架构:-

let questionFields = new Schema({
    title: {
        type: String,
        required: true,
    },
    questionType: {
        type: String,
        required: true,
    },
    sampleAnswer: {
        type: String,
        required: true,
    }
});

和我的查询:-

let recommendationList = await userModel.aggregate([
    {
       $unwind: {
           path: '$questionAnswer',
           preserveNullAndEmptyArrays: true
       }
    },
    {
        $lookup: {
            from: 'questions',
            localField: 'questionAnswer.question',
            foreignField: '_id',
            as: 'questionAnswer'
        }
    },
])

我想要这样的预期输出

{
    name: 'foo',
    phoneNo: '1234567890'
    questionAnswer: [
        {
            question: {
                title: 'This is the first question'
                questionType: 'longQuestion'
                sampleAnswer: 'this is dummy sample answer'
            }
            answer: 'this is my first actual answer'
        },
        {
            question: {
                title: 'This is the second question'
                questionType: 'shortQuestion'
                sampleAnswer: 'this is dummy sample answer'
            }
            answer: 'this is my second actual answer'
        },

    ]
}

【问题讨论】:

  • questions Schema 是什么样子的? @阿西夫
  • @PrasantaBose 我已经用问题模式更新了我的问题。请看一下
  • 见下面我的回答。 @阿西夫
  • 我不确定你是如何插入数据的所以,提供了一个插入代码。如果数据插入正确,可能是不必要的。 @阿西夫

标签: node.js mongodb mongoose aggregation-framework


【解决方案1】:

嗯,_id$lookup 一起使用存在一些问题。因此,您可以使用以下示例。它使用 mongoose 的填充功能。

const mongoose = require("mongoose")
const Schema = mongoose.Schema
const util = require('util')
// util is only used to see a well structured result in console. Else unnecesary
mongoose.connect('mongodb://localhost/stackoverflow', {useNewUrlParser: true});

const questionAnswerSchema = new Schema({
    question: {
        type: mongoose.Schema.ObjectId,
        ref: 'question',
        required: true
    },
    answer: {
        type: String,
        required: true
    },
});

const userSchema =  new Schema({
    name: {
        type: String,
        required: true
    },
    phoneNo: {
        type: String,
        required: true
    },
    questionAnswer: {
        type: [questionAnswerSchema]
    }
});


const questionFields = new Schema({
    title: {
        type: String,
        required: true
    },
    questionType: {
        type: String,
        required: true
    },
    sampleAnswer: {
        type: String,
        required: true
    }
});

const userModel = mongoose.model("user", userSchema)
const questionModel = mongoose.model("question", questionFields)

// Uncomment Insert section and Comment the find section to insert test docs.
// And, keep it current state to fetch results only

// Insert section :
// new questionModel({
//     title: "question title 1",
//     questionType: "type 1",
//     sampleAnswer: "answer 1"
// }).save().then(result => {
//     return new userModel({
//         name: "joker",
//         phoneNo: "999999999",
//         questionAnswer: [
//             {
//                 question: result._id,
//                 answer: "internal answer"
//             }
//         ]
//     }).save()

// }).then((result)=>{
//     console.log("save result", result)
// }).catch(err => {
//     console.log("err",err)
// })

// Find Section
userModel
    .findOne({ name: "joker" })
    .populate("questionAnswer.question","-_id") // may not pass "-_id" as an argument it's here just to hide _id from result
    .then(result => {
        console.log(util.inspect(result, false, null, true /* enable colors */))
    }).catch(err => {
        console.log("err", err)
    })

【讨论】:

  • 我展示的实际用户字段更简单,但是我的用户架构中有很多字段,还有位置字段,这就是我使用聚合和 geoNear 的原因,所以我必须实现这通过使用聚合。
  • 您能分享您的模型结构或您正在尝试实现的内容吗?就像你可以用这个填充任何你想要的字段一样。
【解决方案2】:

您需要在聚合管道中添加更多过滤器。以下是对您的模型的完整聚合查询。希望对您有所帮助!


let recommendationList = await userModel.aggregate([
    {
      $unwind: unwindQuestion
    },
    {
      $lookup: questionLookup
    },
    {
      $unwind: '$datingQuestionAnswer.question'
    },
    {
      $addFields: {
        datingQuestionAnswer: {
          $mergeObjects: ['$datingQuestionAnswer', '$datingQuestionAnswer']
        }
      }
    },
    {
      $group: {
        _id: '$_id',
        datingQuestionAnswer: { $push: '$datingQuestionAnswer' },
      }
    },
    {
      $project: {
        _id: 1,
        datingQuestionAnswer: 1,
        pageNo: 1
      }
    },
])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-04
    • 1970-01-01
    • 2021-10-24
    • 2014-01-12
    • 2022-01-26
    • 1970-01-01
    • 1970-01-01
    • 2016-10-13
    相关资源
    最近更新 更多