$ lookup с конвейером, не заполняющим данные? - PullRequest
1 голос
/ 09 мая 2019

У меня есть две схемы, как следует

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 импортной транзакции будет присутствовать в поле урегулированногоOnImport.

У меня есть сценарий использования, в котором я должен получить детали импорта, а затем из коллекции FmoneyTransaction я должен получить все неурегулированные транзакции, т.е. Я также должен выложить данные фермера при импорте

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 Ответ

1 голос
/ 09 мая 2019

На основании предоставленного CoconutImportSchema, farmerId является ObjectId.В первой агрегации вы ссылаетесь на это в своем операторе "farmerId": "$farmerId", а затем используете его в своем конвейере для сравнения его равенства с другим полем farmerId из коллекции FMoneyTransactions.Так что ObjectId против сравнения ObjectId .И это работает.

Во второй предусмотренной агрегации вы сначала запускаете $lookup на Farmer схеме.Этот $ lookup перезаписывает существующие farmerId.Поскольку $lookup всегда возвращает массив , после этого шага вы получаете массив в поле farmerId.Затем, когда вы пытаетесь определить "farmerId": "$farmerId._id", он возвращает массив, поэтому на этом этапе вы сравниваете массив ObjectIds с ObjectId .Поэтому вы не получаете результатов.

Чтобы исправить это, вы можете запустить $ unwind для farmerId после первого $lookup, если вы уверены, что это соотношение один к одному между CoconutImports и farmer

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"
        }
    }
}])
...