在mongoose和nodejs中查询reference id相同的不同产品价格

hs1rzwqc  于 2023-06-23  发布在  Go
关注(0)|答案(1)|浏览(87)

我有一个文档(名为产品的模型),其结构如下:

{
       "_id" : ObjectId("646ebcd4c24c4fd5d050c5be"),
       "name" : "PRODUCT TEST",
    }

我还有其他文档(一个名为Prices的模型),其结构如下:

注意,以上文档中的id与以下文档中的productId字段匹配。

{
      "_id" : ObjectId("646f8be5c86433269b82fc54"),
      "unitMeasurementId" : ObjectId("646eca3e2fb2ca526a322523"),
      "price" : 100,
      "productId" : ObjectId("646ebcd4c24c4fd5d050c5be")
    }

    {
      "_id" : ObjectId("646f8be5c86433269b82fc55"),
      "unitMeasurementId" : ObjectId("646eca3e2fb2ca526a322524"),
      "price" : 200,
      "productId" : ObjectId("646ebcd4c24c4fd5d050c5be")
    }

    {
      "_id" : ObjectId("646f8be5c86433269b82fc56"),
      "unitMeasurementId" : ObjectId("646eca3e2fb2ca526a322525"),
      "price" : 300,
      "productId" : ObjectId("646ebcd4c24c4fd5d050c5be")
    }

最后,我有这些文档(称为度量单位的模型),其结构如下:

注意,以上文档的unitMeasurementId字段分别与以下文档的_id字段匹配。

{
      "_id" : ObjectId("646eca3e2fb2ca526a322523"),
      "name" : "UNIT"
  }

  {
      "_id" : ObjectId("646eca3e2fb2ca526a322524"),
      "name" : "DOZEN"
  }

  {
      "_id" : ObjectId("646eca3e2fb2ca526a322525"),
      "name" : "HUNDRED"
  }

我尝试在Price模型中查询所有“productId”字段与上面显示的第一个文档(产品模型文档)的“_id”匹配的文档,并按照Price模型中文档的顺序显示它们。model“Units of measure”,即首先是“unitMeasurementId”等于id的价格:“646eca3e2fb2ca526a322523”(度量单位“UNIT”),然后是“unitMeasurementId”等于id的第二个价格:“646eca3e2fb2ca526a322524“(计量单位“DOZEN”),最后是“unitMeasurementId”等于id的价格:“646eca3e2fb2ca526a322525”(度量单位“百”)。
但是,“产品”模型的文件中没有先前的计量单位的价格。例如,一个产品只有两个价格,有两个单位,单位和百,所以它没有一个记录的单位的数量打,在这种情况下,我想填补这个空白时,查询,空。
最后,我想得到的结果如下:

"products": [
       {
            "_id": "646ebcd4c24c4fd5d050c5be",
            "name": "PRODUCT TEST",
            "prices": [
                {
                    "_id": "646f8be5c86433269b82fc54",
                    "unitMeasurementId": {
                        "_id": "646eca3e2fb2ca526a322523",
                        "name": "UNIT",
                    },
                    "price": 100,
                    "productId" : ObjectId("646ebcd4c24c4fd5d050c5be")
                },
                {
                    "_id": "646f8be5c86433269b82fc55",
                    "unitMeasurementId": {
                        "_id": "646eca3e2fb2ca526a322524",
                        "name": "DOZEN",
                    },
                    "price": 200,
                    "productId" : ObjectId("646ebcd4c24c4fd5d050c5be")
                },
                {
                    "_id": "646f8be5c86433269b82fc56",
                    "unitMeasurementId": {
                        "_id": "646eca3e2fb2ca526a322525",
                        "name": "HUNDRED",
                    },
                    "price": 300,
                    "productId" : ObjectId("646ebcd4c24c4fd5d050c5be")
                }
            ]
        },
        {
            "_id": "646ebcd4c24c4fd5d050c5bf",
            "name": "PRODUCT TEST 2",
            "prices": [
                {
                    "_id": "646f8be5c86433269b82fc57",
                    "unitMeasurementId": {
                        "_id": "646eca3e2fb2ca526a322523",
                        "name": "UNIT",
                    },
                    "price": 400,
                    "productId" : ObjectId("646ebcd4c24c4fd5d050c5be")
                },
               null   <----- Place null in case there is no price with that unit of measure
                {
                    "_id": "646f8be5c86433269b82fc59",
                    "unitMeasurementId": {
                        "_id": "646eca3e2fb2ca526a322525",
                        "name": "HUNDRED",
                    },
                    "price": 500,
                    "productId" : ObjectId("646ebcd4c24c4fd5d050c5be")
                }
            ]
        },
  ]

如果该计量单位没有价格,则将其置为空
我已经尝试了以下操作,使用FOR语句,然而,随着文档的增加,响应时间更长,所以我想知道如何使用mongoose进行纯查询:

const getPriceDetails = async (req, res) => {
    try {
        const productsIds = await PriceDetails.find({}).distinct('productId');

        const products = await Product.find({ _id: { $in: productsIds } }, { _id: true, name: true}).lean();

        const unitMeasurements = await UnitMeasurement.find({}).lean();

        for (const product of products) {
            const prices = await Prices.find({ productId: product._id, active: true }, { price: true, unitMeasurementId: true }).sort({ productId: 1 }).populate('unitMeasurementId');

            const c = unitMeasurements.map((i) => prices.find((j) => {
                return j.unitMeasurementId.name === i.name
            }));

            product.prices = c;
        }

        res.send({ products });
    } catch (e) {
        serverError(e, res);
    }

}

我附上了前端的图像以及我如何处理上述信息:

oug3syen

oug3syen1#

mongoDB内部的高级连接应该使用mongoDB aggregation pipeline
这比在普通代码中手动进行连接(如在函数getPriceDetails中所做的)要好。
下面是一个聚合管道,它返回你想要的数据:

{
   "aggregate": "products",
   "pipeline": [
      {
         "$lookup": {
            "from": "prices",
            "let": {
               "i": "$_id"
            },
            "pipeline": [
               {
                  "$match": {
                     "$expr": {
                        "$eq": [
                           "$productId",
                           "$$i"
                        ]
                     }
                  }
               },
               {
                  "$project": {
                     "unitMeasurementId": 1,
                     "price": 1
                  }
               }
            ],
            "as": "prices"
         }
      },
      {
         "$unwind": {
            "path": "$prices"
         }
      },
      {
         "$lookup": {
            "from": "units",
            "localField": "prices.unitMeasurementId",
            "foreignField": "_id",
            "as": "prices.unit"
         }
      },
      {
         "$unwind": {
            "path": "$prices.unit"
         }
      },
      {
         "$project": {
            "name": 1,
            "prices._id": 1,
            "prices.price": 1,
            "prices.unit": {
               "name": "$prices.unit.name",
               "_id": "$prices.unit._id"
            }
         }
      },
      {
         "$group": {
            "_id": {
               "name": "$name",
               "_id": "$_id"
            },
            "prices": {
               "$push": "$prices"
            }
         }
      },
      {
         "$project": {
            "_id": "$_id._id",
            "name": "$_id.name",
            "prices": "$prices"
         }
      },
      {
         "$limit": 10
      }
   ]
}

你需要调整参数limitskip,这样你就不会为每个请求一次获取所有的数据库数据,而是只获取需要的数据。

相关问题