Mongoose聚合$lookup在'作为'字段



假设我们有两个集合:OrderSeller,用于类似Ebay的业务,客户可以从单个卖家那里订购商品。

每个Order包含一个seller字段,该字段列出店主的ID。

const orderSchema = new mongoose.Schema({
seller: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'Seller' },
item: { type: String },
});
const Order = mongoose.model('Order', orderSchema);

当我尝试使用$lookup 时

const aggregateOrdersWithSellerInfo = await Order.aggregate([
{
$lookup: {
from: 'Seller',
localField: 'seller',
foreignField: '_id',
as: 'seller_info',
},
},
]).exec();

所有seller_info字段(例如:aggregateOrdersWithSellerInfo[0].seller_info)都返回一个空数组:

> (0) []

但我希望它返回与每个Order上的seller字段相关联的卖家,例如:

// Seller doc
{
_id: ObjectId("62aa38d68e006f3006efe520"),
firstName: 'Nikki',
__v: 0
}

以下是订单文档的示例

{
_id: ObjectId("62aa38d68e006f3006efe522"),
seller: ObjectId("62aa38d68e006f3006efe520"),
item: 'Mango Body Butter',
__v: 0
}

如何使用聚合获取关联的卖家文档

完整代码

const mongoose = require('mongoose');
const connect = async (dsn) =>
mongoose.connect(dsn, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
// Order Schema
const orderSchema = new mongoose.Schema({
seller: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'Seller' },
item: { type: String },
});
const Order = mongoose.model('Order', orderSchema);
// Seller Schema
const sellerSchema = new mongoose.Schema({
firstName: { type: String },
});
const Seller = mongoose.model('Seller', sellerSchema);
// Seeder
const seedLocalDatabase = async () => {
await connect('mongodb://127.0.0.1:27017/fakewishtender');
await Seller.deleteMany({});
const sellers = [
{
firstName: 'Nikki',
},
{
firstName: 'Alice',
},
];
const sellersInsertedRes = await Seller.insertMany(sellers);
await Order.deleteMany({});
const orders = [
{
seller: sellersInsertedRes.find((seller) => seller.firstName === 'Nikki')._id,
item: 'Mango Body Butter',
},
{
seller: sellersInsertedRes.find((seller) => seller.firstName === 'Alice')._id,
item: 'Vintage Jacket',
},
];
await Order.insertMany(orders);
};
// Aggregation
(async () => {
await seedLocalDatabase();
const aggregateOrdersWithSellerInfo = await Order.aggregate([
{
$lookup: {
from: 'Seller',
localField: 'seller',
foreignField: '_id',
as: 'seller_info',
},
},
]).exec();
const allSellers = await Seller.find({});
const allOrders = await Order.find({});
const sellersWithOrders = allOrders.map((order) =>
allSellers.filter((seller) => seller._id.toJSON() === order.seller.toJSON())
);
const sellersPopulatedWithAggregate = aggregateOrdersWithSellerInfo.map(
(order) => order.seller_info
);
console.log(
`

Sellers populated with aggregation are: 

${JSON.stringify(sellersPopulatedWithAggregate)}

`
);
console.log(
`But I would expect sellers populated with aggregation to be: 

${JSON.stringify(sellersWithOrders)}

`
);
mongoose.disconnect();
})();

问题在于集合的名称。

Seller.collection.collectionName保存集合名称'sellers',因此复数小写

const aggregateOrdersWithSellerInfo = await Order.aggregate([
{
$lookup: {
from: 'sellers',
localField: 'seller',
foreignField: '_id',
as: 'seller_info',
},
},
]).exec();

您也可以执行from: Seller.collection.collectionName,而不是静态键入名称

最新更新