假设我们有两个集合:Order
和Seller
,用于类似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
,而不是静态键入名称