加速和简化MongoDB聚合功能



我有以下函数,这是相当复杂的,但我希望有人能理解它,帮助我简化/加速它。

在这个函数中,我最后得到一个数组,其中包含primaryStores的列表以及从每个商店到我的商店组的产品数量。但是,如果该商店与正在讨论的特定主要商店有可接受的连接,则只计算产品。(有些可能已接受其中一个连接,而另一个尚未接受)

我将试着解释它是如何工作的:

我向函数传递了一个storeid列表。我循环遍历每个主存储,以找出每个主存储与哪些主存储有可接受的连接。在那些被接受的连接中,我只得到商店ID。然后,我找出我的商店中有哪些产品,并获得产品ID以及将它们连接到我的商店的链接ID。然后我开始我的聚合函数,它首先查找我的哪些产品与另一个商店有联系。然后,我查找其他商店信息,以获得商店ID和过滤器,只得到我连接到的。然后,我将其投影并按商店id/名称分组,并获得来自每个主要商店的产品总数和包含每个主要商店的所有产品列表的数组。我将每个主商店的每个连接的primaryStore推入一个名为' allfeedstores '的数组。

当我循环遍历每个主存储时,每次一个来获取此信息。最后,我有一个reduce函数,它将数组中出现的任何重复的primaryStores组合起来,并连接总产品。这为我提供了一个关于我所有主要商店的大部分产品来自哪里的概述。

我试图在开始时摆脱for循环,所以我不必一次遍历每个store。但是我不知道,如果不把两个单独的商店分开,我怎么能检查它们之间是否存在已签名的连接。

不太可能有人会理解这一点,但如果有人能帮助我,我会非常感激!下面是我的代码:
async getFeederStores(storeIDs): Promise<any[]> {
let allFeederStores = [];
for (let storeID of storeIDs) {
//get all the signed connections this store has with primary stores
const linkedPrimaryStores = await this.linkedStoreModel.aggregate([
{
$match: {
main_store: storeID,
primary_store_signed_by: { $ne: null },
},
},
]);
//get just the primary store ids from the linked primary stores
const primaryStoreIDs = linkedPrimaryStores.map((linkedPrimaryStore) => {
return linkedPrimaryStore.primary_store;
});
//get all products from this store
const products = await this.productStoreModel
.find({
store: storeID,
})
.select("product")
.lean();
//get product ids from this store
const productIDs = products.map((product) => {
return product.product;
});
//get the product store ids
const productStoreIDs = products.map((product) => {
return product._id;
});
const linkedStores = await this.productStoreModel.aggregate([
{
//get the products connected to other stores
$match: {
product: {
$in: productIDs,
},
_id: {
$nin: productStoreIDs,
},
},
},
//look up the other stores info
{
$lookup: {
from: "stores",
localField: "store",
foreignField: "_id",
as: "store",
},
},
//unwind the stores info
{
$unwind: "$store",
},
//filter to only get primary stores that are connected to this main store
{
$match: {
"store._id": { $in: primaryStoreIDs },
},
},
//project to only get the store id/name and the product store id
{
$project: {
"store._id": 1,
"store.name": 1,
product_store: "$_id",
},
},
//group by store - get the total number of products coming from each store and the products info from each one
{
$group: {
_id: "$store._id",
name: { $first: "$store.name" },
total_products: { $sum: 1 },
products: {
$push: {
product_store: "$product_store ",
},
},
},
},
]);
for (let primaryStore of linkedPrimaryStores) {
allFeederStores.push(primaryStore);
}
}
//loop through all the feeder stores
//any duplicate stores, combine the total number of products and the products array
let concatenatedPrimaryStores = allFeederStores.reduce((accum, cv) => {
const index = accum.findIndex((item) => item._id === cv._id);
if (index === -1) {
accum.push(cv);
} else {
accum[index].total_products += ", " + cv.total_products;
accum[index].products += ", " + cv.products;
}
return accum;
}, []);
return concatenatedPrimaryStores;
}

我在下面添加了一些示例数据。在本例中,MainStore1与PrimaryStore1有一个带签名的连接,但与PrimaryStore1没有连接(因此来自该主商店的任何产品都不会被计算在此主商店中)然而,MainStore2与PrimaryStore1和PrimaryStore2都有一个签名连接,(因此来自这两个主商店的任何产品都将被计算在这个主商店中)

db={
"storesModel": [
{
"_id": "Main1",
"name": "Main Store 1",
},
{
"_id": "Main2",
"name": "Main Store 1",
},
{
"_id": "Primary1",
"name": "Primary Store 1",
},
{
"_id": "Primary2",
"name": "Primary Store 2",
},
],
"linkedStoreModel": [
{
"_id": "LS1",
"main_store": "Main1",
"primary_store_signed_by": 'Bob',
"primary_store": "Primary1"
},
{
"_id": "LS2",
"main_store": "Main2",
"primary_store_signed_by": 'Bill',
"primary_store": "Primary1"
},
{
"_id": "LS3",
"main_store": "Main1",
"primary_store_signed_by": null,
"primary_store": "Primary2"
},
{
"_id": "LS4",
"main_store": "Main2",
"primary_store_signed_by": 'Betty',
"primary_store": "Primary2"
}
],
"productStoreModel": [
{
"_id": "PS1",
"store": "Main1",
"product": "Product1"
},
{
"_id": "PS2",
"store": "Main2",
"product": "Product1"
},
{
"_id": "PS3",
"store": "Main1",
"product": "Primary2"
},
{
"_id": "PS4",
"store": "Main2",
"product": "Primary2"
},
]
}

期望的输出是这样的:

concatenatedPrimaryStores:
[
{  primaryStoreName:  “Primary1”,
total_products: “2”,
products: {array containing products}
}
{  primaryStoreName:  “Primary2”,
total_products: “1”,
products: {array containing products}
}
]

如果我正确理解了您的逻辑,则此聚合管道返回每个"primary_store"的产品数量和产品列表,其中产品来自"signed"&;"main_store".

db.linkedStoreModel.aggregate([
{ // get "signed" mains for each primary
"$group": {
"_id": "$primary_store",
"signedMains": {
"$addToSet": {
"$cond": [
{"$ne": ["$primary_store_signed_by", null]},
"$main_store",
null
]
}
}
}
},
{ // get all products for signedMains
"$lookup": {
"from": "productStoreModel",
"localField": "signedMains",
"foreignField": "store",
"pipeline": [
{
"$group": {
"_id": null,
"products": {"$addToSet": "$product"}
}
}
],
"as": "productList"
}
},
{ // format output
"$project": {
"_id": 0,
"primaryStoreName": "$_id",
"total_products": {
"$size": {"$ifNull": [{"$first": "$productList.products"}, [] ]}
},
"products": {"$first": "$productList.products"}
}
}
])

在mongoplayground.net上试试。

相关内容

  • 没有找到相关文章

最新更新