聚合以在文档中插入数组值

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"
                        ...
             }
       }
}
])

我的疑惑是:

查询

  • 在每个文档中添加列表(代码)
  • 展开代码
  • 过滤每个数组,使 Code 存在于数组中且数量>=3
  • 如果筛选结果为空,则 Codeout of stock
  • 其他it is in stock

PlayMongo

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

*主要区别在于在每个文档中本地工作, 并且只在完成后放松,也许会更快

PlayMongo

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

PlayMongo

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"}}])