聚合以在文档中插入数组值
Aggregate to insert array values in a document
我有以下合集
{
"Id" : "12345-7",
},
"Stock" : [
{
"Code" : "1",
"Qty" : 5.0
},
{
"Code" : "3",
"Qty" : 7.0
}
]
}
{
"Id" : "22222-0",
"Stock" : [
{
"Code" : "3",
"Qty" : 10.0
},
{
"Code" : "10",
"Qty" : 2.0
}
]
}
我有这个列表:
{1 , 10}
我的预期输出是:
Id : 12345-7
Code: 1
Availability : in stock
Id : 12345-7
Code: 10
Availability : out of stock
Id : 12345-7
Code: 1
Availability : out of stock
Id : 12345-7
Code: 10
Availability : out of stock
基本上,如果 Stock.Code
中不存在列表的值,我需要生成一个包含列表值的文档。预期输出的最后一个文档是 out of stock
因为有一条规则是 in stock
if Qty >= 3
我试过了
db.Collection.aggregate([
{
"$unwind" : "$Stock"
},
{
"$match" :
{
"$in" : ["Stock.Code", list]
}
},
{
"$projoect" :
{
"Id" : "$Id",
"Code" : "$Stock.Code",
"Availability" :
{
"$cond"
...
}
}
}
])
我的疑惑是:
- 我可以只使用一个集合来做到这一点吗?
- 最好的方法是什么?我正在使用 pyMongo 来编写代码,最好在数据库端或代码端执行此操作
- 如何更改聚合
Code
和 Condition
以匹配我的预期输出?
查询
- 在每个文档中添加列表(代码)
- 展开代码
- 过滤每个数组,使
Code
存在于数组中且数量>=3
- 如果筛选结果为空,则
Code
为 out of stock
- 其他
it is in stock
aggregate(
[{"$set": {"Code": ["1", "10"]}},
{"$unwind": {"path": "$Code"}},
{"$set":
{"Availability":
{"$cond":
[{"$eq":
[{"$filter":
{"input": "$Stock",
"cond":
{"$and":
[{"$gte": ["$$this.Qty", 3]},
{"$eq": ["$$this.Code", "$Code"]}]}}},
[]]},
"out of stock","in stock"]}}},
{"$project": {"_id": 0, "Id": 1, "Code": 1, "Availability": 1}}])
Edit1(数组运算符)
如果你想试试这个,它试图将事情保持在本地,并且只有在完成后才展开。
查询
- 从库存中保留也在代码列表中的代码
- 缺货代码 = 缺失代码(作为文件)
- 库存代码 = 找到的代码(作为文档)
- concat 有货,无货,项目
- 展开并用这些子文档替换 root
*主要区别在于在每个文档中本地工作,
并且只在完成后放松,也许会更快
aggregate(
[{"$set": {"codes": ["1", "10"]}},
{"$set":
{"Stock":
{"$reduce":
{"input": "$Stock",
"initialValue": [],
"in":
{"$cond":
[{"$and":
[{"$gte": ["$$this.Qty", 3]},
{"$in": ["$$this.Code", "$codes"]}]},
{"$concatArrays": ["$$value", ["$$this.Code"]]}, "$$value"]}}}}},
{"$set":
{"out-stock":
{"$map":
{"input": {"$setDifference": ["$codes", "$Stock"]},
"in":
{"Id": "$Id", "Code": "$$this", "Availability": "out of stock"}}}}},
{"$set":
{"in-stock":
{"$map":
{"input": "$Stock",
"in":
{"Id": "$Id", "Code": "$$this", "Availability": "in stock"}}}}},
{"$project":
{"stock-info": {"$concatArrays": ["$out-stock", "$in-stock"]}}},
{"$unwind": {"path": "$stock-info"}},
{"$replaceRoot": {"newRoot": "$stock-info"}}])
Edit2(数组运算符并保留数量)
如果你想保持数量也可以试试这个。
它有点不同,也许它比两者都快,但我无法测试它。
如果 code 存在于 Id 上,它将具有它的数量,否则它将具有数量 0(如果找不到代码,您可以输入任何值,甚至完全删除该字段)更改此部分 "Qty": 0
查询
- map Stock,code-list中的codes,变成documents with
Availability
进出斯托克,其他值映射到 null
- 找到missing-codes=没有库存的代码,比如第一个连代码10都没有,做成out-of-stock和qty=0的文件
- concat 在库存中找到代码和缺失代码
- 展开并替换 root
aggregate(
[{"$set": {"codes": ["1", "10"]}},
{"$set":
{"Stock":
{"$map":
{"input": "$Stock",
"in":
{"$switch":
{"branches":
[{"case":
{"$and":
[{"$gte": ["$$this.Qty", 3]},
{"$in": ["$$this.Code", "$codes"]}]},
"then":
{"$mergeObjects":
["$$this", {"Availability": "in stock", "Id": "$Id"}]}},
{"case": {"$in": ["$$this.Code", "$codes"]},
"then":
{"$mergeObjects":
["$$this", {"Availability": "out of stock", "Id": "$Id"}]}}],
"default": null}}}}}},
{"$set":
{"Stock":
{"$filter": {"input": "$Stock", "cond": {"$ne": ["$$this", null]}}},
"missing-codes":
{"$map":
{"input": {"$setDifference": ["$codes", "$Stock.Code"]},
"in":
{"Availability": "out of stock",
"Id": "$Id",
"Code": "$$this",
"Qty": 0}}}}},
{"$project":
{"_id": 0, "Stock": {"$concatArrays": ["$Stock", "$missing-codes"]}}},
{"$unwind": {"path": "$Stock"}},
{"$replaceRoot": {"newRoot": "$Stock"}}])
我有以下合集
{
"Id" : "12345-7",
},
"Stock" : [
{
"Code" : "1",
"Qty" : 5.0
},
{
"Code" : "3",
"Qty" : 7.0
}
]
}
{
"Id" : "22222-0",
"Stock" : [
{
"Code" : "3",
"Qty" : 10.0
},
{
"Code" : "10",
"Qty" : 2.0
}
]
}
我有这个列表:
{1 , 10}
我的预期输出是:
Id : 12345-7
Code: 1
Availability : in stock
Id : 12345-7
Code: 10
Availability : out of stock
Id : 12345-7
Code: 1
Availability : out of stock
Id : 12345-7
Code: 10
Availability : out of stock
基本上,如果 Stock.Code
中不存在列表的值,我需要生成一个包含列表值的文档。预期输出的最后一个文档是 out of stock
因为有一条规则是 in stock
if Qty >= 3
我试过了
db.Collection.aggregate([
{
"$unwind" : "$Stock"
},
{
"$match" :
{
"$in" : ["Stock.Code", list]
}
},
{
"$projoect" :
{
"Id" : "$Id",
"Code" : "$Stock.Code",
"Availability" :
{
"$cond"
...
}
}
}
])
我的疑惑是:
- 我可以只使用一个集合来做到这一点吗?
- 最好的方法是什么?我正在使用 pyMongo 来编写代码,最好在数据库端或代码端执行此操作
- 如何更改聚合
Code
和Condition
以匹配我的预期输出?
查询
- 在每个文档中添加列表(代码)
- 展开代码
- 过滤每个数组,使
Code
存在于数组中且数量>=3 - 如果筛选结果为空,则
Code
为out of stock
- 其他
it is in stock
aggregate(
[{"$set": {"Code": ["1", "10"]}},
{"$unwind": {"path": "$Code"}},
{"$set":
{"Availability":
{"$cond":
[{"$eq":
[{"$filter":
{"input": "$Stock",
"cond":
{"$and":
[{"$gte": ["$$this.Qty", 3]},
{"$eq": ["$$this.Code", "$Code"]}]}}},
[]]},
"out of stock","in stock"]}}},
{"$project": {"_id": 0, "Id": 1, "Code": 1, "Availability": 1}}])
Edit1(数组运算符)
如果你想试试这个,它试图将事情保持在本地,并且只有在完成后才展开。
查询
- 从库存中保留也在代码列表中的代码
- 缺货代码 = 缺失代码(作为文件)
- 库存代码 = 找到的代码(作为文档)
- concat 有货,无货,项目
- 展开并用这些子文档替换 root
*主要区别在于在每个文档中本地工作, 并且只在完成后放松,也许会更快
aggregate(
[{"$set": {"codes": ["1", "10"]}},
{"$set":
{"Stock":
{"$reduce":
{"input": "$Stock",
"initialValue": [],
"in":
{"$cond":
[{"$and":
[{"$gte": ["$$this.Qty", 3]},
{"$in": ["$$this.Code", "$codes"]}]},
{"$concatArrays": ["$$value", ["$$this.Code"]]}, "$$value"]}}}}},
{"$set":
{"out-stock":
{"$map":
{"input": {"$setDifference": ["$codes", "$Stock"]},
"in":
{"Id": "$Id", "Code": "$$this", "Availability": "out of stock"}}}}},
{"$set":
{"in-stock":
{"$map":
{"input": "$Stock",
"in":
{"Id": "$Id", "Code": "$$this", "Availability": "in stock"}}}}},
{"$project":
{"stock-info": {"$concatArrays": ["$out-stock", "$in-stock"]}}},
{"$unwind": {"path": "$stock-info"}},
{"$replaceRoot": {"newRoot": "$stock-info"}}])
Edit2(数组运算符并保留数量)
如果你想保持数量也可以试试这个。 它有点不同,也许它比两者都快,但我无法测试它。
如果 code 存在于 Id 上,它将具有它的数量,否则它将具有数量 0(如果找不到代码,您可以输入任何值,甚至完全删除该字段)更改此部分 "Qty": 0
查询
- map Stock,code-list中的codes,变成documents with
Availability
进出斯托克,其他值映射到 null - 找到missing-codes=没有库存的代码,比如第一个连代码10都没有,做成out-of-stock和qty=0的文件
- concat 在库存中找到代码和缺失代码
- 展开并替换 root
aggregate(
[{"$set": {"codes": ["1", "10"]}},
{"$set":
{"Stock":
{"$map":
{"input": "$Stock",
"in":
{"$switch":
{"branches":
[{"case":
{"$and":
[{"$gte": ["$$this.Qty", 3]},
{"$in": ["$$this.Code", "$codes"]}]},
"then":
{"$mergeObjects":
["$$this", {"Availability": "in stock", "Id": "$Id"}]}},
{"case": {"$in": ["$$this.Code", "$codes"]},
"then":
{"$mergeObjects":
["$$this", {"Availability": "out of stock", "Id": "$Id"}]}}],
"default": null}}}}}},
{"$set":
{"Stock":
{"$filter": {"input": "$Stock", "cond": {"$ne": ["$$this", null]}}},
"missing-codes":
{"$map":
{"input": {"$setDifference": ["$codes", "$Stock.Code"]},
"in":
{"Availability": "out of stock",
"Id": "$Id",
"Code": "$$this",
"Qty": 0}}}}},
{"$project":
{"_id": 0, "Stock": {"$concatArrays": ["$Stock", "$missing-codes"]}}},
{"$unwind": {"path": "$Stock"}},
{"$replaceRoot": {"newRoot": "$Stock"}}])