$ lookup和管道未填充数据?

时间:2019-05-09 04:01:24

标签: mongodb mongoose aggregation-framework

我有以下两种模式

const CoconutImportSchema = new Schema({
    userId: {
        type: Schema.Types.ObjectId,
        ref: 'User',
        required: true
    },
    farmerId: {
        type: Schema.Types.ObjectId,
        ref: 'Farmer'
    },
    settledOn: {
        type: Date,
        default: null
    },
    importedOn: {
        type: Date,
        default: Date.now()
    }

},
    { toJSON: { virtuals: true } }
)

const FMoneyTransactionSchema = new Schema({
    userId: {
        type: Schema.Types.ObjectId,
        ref: 'User',
        required: true
    },
    farmerId: {
        type: Schema.Types.ObjectId,
        ref: 'Farmer'
    },
    amount: {
        type: Number,
        required: true
    },
    date: {
        type: Date,
        default: Date.now()
    },
    settledOnImport: {
        type: Schema.Types.ObjectId,
        ref:'CoconutImport',
        default:null
    }
})

CoconutImport中的每个交易都可能在Fmonetrasanction中有多个记录。如果FmoneyTransaction中的交易已结算,则导入交易的_id将出现在resolvedOnImport字段中。

我有一个用例,其中我必须获取导入的详细信息,然后必须从集合FmoneyTransaction中获取所有未结算的交易,即,settedOnImport = null。我还必须在导入中弹出农夫详细信息

await CoconutImports.aggregate([
        {
            $match: {
                _id: Types.ObjectId(importId),
                userId: Types.ObjectId(userId)
            }

        },
        {
            $lookup: {
                from: FMoneyTransactions.collection.name,
                "let": {
                    "farmerId": "$farmerId"
                },
                pipeline: [
                    {
                        $match: {
                            $expr: {
                                $and: [

                                    {
                                        $eq: [
                                            "$$farmerId",
                                            "$farmerId"
                                        ]
                                    },
                                    {
                                        $eq: [
                                            "$settledOnImport", null
                                        ]
                                    }
                                ]

                            }
                        }

                    }
                ],
                as: "unsettledMoneyTransactions"
            }
        },
        {
            $lookup: {
                from: Farmer.collection.name,
                localField: 'farmerId',
                foreignField: '_id',
                as: 'farmerId'
            }
        },

这有效,但以下内容无效

await CoconutImports.aggregate([
        {
            $match: {
                _id: Types.ObjectId(importId),
                userId: Types.ObjectId(userId)
            }

        },

        {
            $lookup: {
                from: Farmer.collection.name,
                localField: 'farmerId',
                foreignField: '_id',
                as: 'farmerId'
            },
        {
            $lookup: {
                from: FMoneyTransactions.collection.name,
                "let": {
                    "farmerId": "$farmerId._id"
                },
                pipeline: [
                    {
                        $match: {
                            $expr: {
                                $and: [

                                    {
                                        $eq: [
                                            "$$farmerId",
                                            "$farmerId"
                                        ]
                                    },
                                    {
                                        $eq: [
                                            "$settledOnImport", null
                                        ]
                                    }
                                ]

                            }
                        }

                    }
                ],
                as: "unsettledMoneyTransactions"
            }
        }
        }])

有人可以解释为什么吗?

1 个答案:

答案 0 :(得分:1)

基于提供的CoconutImportSchemafarmerIdObjectId。在第一个聚合中,您在"farmerId": "$farmerId"语句中引用了它,然后在管道中使用它来比较它与farmerId集合中其他FMoneyTransactions字段的相等性。因此,将 ObjectId与ObjectId 进行比较。而且有效。

在第二个提供的聚合中,您首先在$lookup模式上运行Farmer。该$lookup覆盖现有的farmerId。由于$lookup总是返回数组,因此在此步骤之后,您将在farmerId字段下获得一个数组。然后,当您尝试定义"farmerId": "$farmerId._id"时,它会返回一个数组,因此在该步骤中,您将 ObjectIds数组 ObjectId 进行比较。因此,您没有任何结果。

要解决此问题,如果您确定farmerId$lookup之间是一对一的关系,则可以在第一个CoconutImports之后在$ farmer上运行$ unwind < / p>

await CoconutImports.aggregate([
    {
        $match: {
            _id: Types.ObjectId(importId),
            userId: Types.ObjectId(userId)
        }
    },
    {
        $lookup: {
            from: Farmer.collection.name,
            localField: 'farmerId',
            foreignField: '_id',
            as: 'farmerId'
        },
    },
    {   $unwind: "$farmerId" },
    {
        $lookup: {
            from: FMoneyTransactions.collection.name,
            "let": {
                "farmerId": "$farmerId._id"
            },
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $and: [

                                {
                                    $eq: [
                                        "$$farmerId",
                                        "$farmerId"
                                    ]
                                },
                                {
                                    $eq: [
                                        "$settledOnImport", null
                                    ]
                                }
                            ]

                        }
                    }
                }
            ],
            as: "unsettledMoneyTransactions"
        }
    }
}])