加快并简化mongoDB聚合功能
我有以下功能,这很复杂,但是我希望有人能够理解它可以帮助我简化/加快速度。
在此功能中,我最终获得了一个数组,其中包含主要商店列表以及从每个商店到我的商店的产品数量。但是,只有该商店与所讨论的特定主要商店有公认的连接,它才会计算产品。 (有些人可能与一个接收的连接,而不是另一个连接)
我将尝试解释它的工作原理:
我将storeID的列表传递到该函数中。我循环浏览每个循环,以找出每个主要存储都具有可接受的连接。 在那些具有公认连接的人中,我只获得了商店ID。 然后,我找出商店中的产品,并获取产品ID和将其连接到我的商店的链接ID。 然后,我开始我的汇总功能,该功能首先要查找我的哪些产品与另一家商店有连接。然后,我查找其他存储信息以获取商店ID并过滤以仅获取我已连接的信息。然后,我按商店ID/名称进行项目和组进行投影,并获取来自每个主要商店的产品总数,以及一个包含每个产品列表的阵列。 我将每个主要商店的每个连接的主库推到一个名为“ AllFeederStores”的数组中。
当我一次遍历每个主要商店时,以获取此信息。最后,我有一个降低功能,可以结合出现在我阵列中的任何重复的主要商店,并加入总产品。这为我提供了有关我所有主要商店的大多数产品的概述。
我试图在一开始就摆脱for循环,因此我不必一次循环。但是我不知道,如何在两个单独的商店之间进行检查,而无需分开。
没有人会理解这一点,但是如果有人这样做并且可以帮助我,我将非常感谢它!
以下是我的代码:
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;
}
我在下面添加了一些示例数据。在这种情况下 但是,Mainstore2与primary store1和primary store2都有签名的连接(因此,这两个主要商店都将计算出此主要商店的任何产品)
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}
}
]
I have the following function, which is quite complicated, but i'm hoping someone might be able to understand it help me simplify/speed it up.
In this function i end up with an array that contains a list of primaryStores and the number of products coming from each one to my group of stores. However, it only counts the products, if that store has an accepted connection with the particular primary store in question. (Some might have an accepted connection to one and not the other yet)
I will try and explain how it works:
I pass into the function a list of storeIDs. I loop through each one to find out which primary stores each one has an accepted connection with.
Out of those with an accepted connection, i just get the store ID.
I then find out what products are in my store, and get the product IDs and the linked ID connecting them to my store.
I then begin my aggregate function which starts off by finding which of my products have a connection to another store. I then look up the other stores info to get the store ID and filter to only get ones i am connected to. I then project this and group by store id/name and get the total number of products coming from each primary store and an array containing a list of all the products from each one.
I push each connected primaryStore for each of my main stores into an array called 'allFeederStores'.
As i am looping through each of my main stores one at a time to get this information. At the end I have a reduce function which combines any duplicating primaryStores that appear in my array, and concatenate the total products. This provides my with an overview of where the majority of my products are coming from for all of my main stores.
I am trying to get rid of the for loop at the beginning, so i don't have to loop through each store at once. But i can't figure out, how i can check a signed connection exists between the two individual stores without doing them seperate.
It's not likely anyone will understand this, but if anyone does and can help I would much appreciate it!
Below is my code:
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;
}
I have added some sample data below. In this case MainStore1 has a signed connection with PrimaryStore1 but not PrimaryStore1 (so any products coming from that primary store won't be counted for this main store)
However MainStore2 has a signed connection with both PrimaryStore1 and PrimaryStore2, (so any products coming from both those primary stores will be counted for this main store)
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"
},
]
}
Expected output is something like this:
concatenatedPrimaryStores:
[
{ primaryStoreName: “Primary1”,
total_products: “2”,
products: {array containing products}
}
{ primaryStoreName: “Primary2”,
total_products: “1”,
products: {array containing products}
}
]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果我正确理解您的逻辑,则此聚合管道将返回每个
“ primary_store”
的产品的数量和列表,其中产品来自“签名”“ main_store” 。
尝试一下 mongoplayground.net.net 。
If I understand your logic correctly, this aggregation pipeline returns the number of, and list of, products for each
"primary_store"
where the products come from a "signed""main_store"
.Try it on mongoplayground.net.