mongodb - 猫鼬递归嵌套
问题描述
在我的项目中,用户可以创建产品。每个用户都有对其所有产品的引用,每个产品都有对其用户的引用。
用户和产品都有一个“名称”字段。
我需要获取所有用户产品数组,并且在该数组中我想拥有产品名称和创建它的用户名(并且只有那些字段,没有其他字段)。
例如:
用户:
{ _id: 1, name: 'josh', productIds: [1,3]}
{ _id: 2, name: 'sheldon', productIds: [2]}
产品:
{ _id: 1, name: 'table', price: 45, userId: 1}
{ _id: 2, name: 'television', price: 25 userId: 2}
{ _id: 3, name: 'chair', price: 14 userId: 1}
我想得到以下结果:
{ _id: 1, name: 'josh',
products: {
{ _id: 1, name: 'table', user: { _id: 1, name: 'josh' },
{ _id: 3, name: 'chair', user: { _id: 1, name: 'josh' },
}
}
{ _id: 2, name: 'sheldon',
products: {
{ _id: 2, name: 'television', userId: { _id: 2, name: 'sheldon' }
}
}
我尝试了以下未填充内部 userId 的查询,只留下了 id(无名称):
User.aggregate([
{
$lookup:
{
from: 'products',
localField: 'productIds',
foreignField: '_id',
as: 'products'
}
}
我还尝试了以下操作,它与第一个查询相同,只是它只为每个用户重试了第一个产品:
User.aggregate([
{
$lookup:
{
from: 'products',
localField: 'productIds',
foreignField: '_id',
as: 'products'
}
},
{
$unwind: {
path: "$products",
preserveNullAndEmptyArrays: true
}
},
{
$lookup: {
from: "user",
localField: "products.userId",
foreignField: "_id",
as: "prodUsr",
}
},
{
$group: {
_id : "$_id",
products: { $push: "$products" },
"doc": { "$first": "$$ROOT" }
}
},
{
"$replaceRoot": {
"newRoot": "$doc"
}
}
产品:
const schema = new Schema(
{
name: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
userId: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
}
);
module.exports = mongoose.model('Product', schema);
用户:
const schema = new Schema(
{
name: {
type: String,
required: true,
unique: true
},
productIds: [{
type: Schema.Types.ObjectId,
ref: 'Product',
require: false
}],
{ timestamps: true }
);
module.exports = mongoose.model('User', schema);
任何帮助将不胜感激
解决方案
对于带有自定义管道和另一个嵌套的 $lookup 来说,这看起来像是一个完美的场景$lookup
。内层允许您处理product-> user
关系,而外层则处理关系user -> product
:
db.Users.aggregate([
{
$project: {
productIds: 0
}
},
{
$lookup: {
from: "Products",
let: { user_id: "$_id" },
pipeline: [
{
$match: {
$expr: {
$eq: [ "$userId", "$$user_id" ]
}
}
},
{
$lookup: {
from: "Users",
localField: "userId",
foreignField: "_id",
as: "user"
}
},
{
$unwind: "$user"
},
{
$project: {
"user.productIds": 0,
"price": 0,
"userId": 0
}
}
],
as: "products"
}
}
])
推荐阅读
- javascript - 是否有任何功能可以检测站点域已更改?
- catboost - 使用 onnx 保存 catboost 模型时,可以保存和使用客户参数吗?
- ruby-on-rails - Rails - 由于 spring gem 无法运行 rails 服务器
- c# - 两种不同类型的字典并转换为 JSON
- java - 错误:不兼容的类型:int 无法转换为 String
- java - 使用 JAVA Spring Boot 创建评论系统后端服务器
- java - Java Swing - 方法 getComponents 仅返回一个组件
- python - 如何使这个函数以数组数组作为输入用 numba 编译?
- javascript - 在逐个节点的基础上设计 react-treebeard
- typescript - for 循环内的 const