【问题标题】:Aggregate to insert array values in a document聚合以在文档中插入数组值
【发布时间】:2021-11-10 22:34:56
【问题描述】:

我有以下收藏

{
    "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 进行编码,最好在数据库端或代码端执行此操作
  • 如何更改我的聚合 CodeCondition 以匹配我的预期输出?

【问题讨论】:

  • 你确定这不是一个错误吗?编号:12345-7 代码:10 可用性:有货,12345-7 根本没有代码 10
  • @Takis_ 这是一个错字,我已经编辑了答案,现在是正确的!谢谢
  • 下面的答案对你有用吗?这就是你需要的?
  • 我现在测试一下,等我写完我就在这里发帖,等会儿
  • 我的收藏中有 2kk 个寄存器

标签: mongodb aggregation-framework aggregate


【解决方案1】:

查询

  • 在每个文档中添加列表(代码)
  • 展开代码
  • 过滤每个数组以使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(数组运算符)

如果你也想试试这个,它会尽量保持本地化,只有在完成后才会放松。

查询

  • 库存保留代码列表中的代码
  • 缺货代码 = 缺失代码(作为文档)
  • 库存代码 = 找到的代码(作为文档)
  • 有现货,无现货,项目
  • 展开并用这些子文档替换 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(数组运算符并保​​留数量)

如果你想保持数量也可以试试这个。 它有点不同,也许它比两者都快,但我无法测试它。

如果代码存在于 Id 上,它将具有它的数量,否则它将具有数量 0(如果找不到代码,您可以输入任何值,甚至完全删除该字段)更改此部分 "Qty": 0

查询

  • map Stock,代码列表中的代码,变成文档 Availability in 或 out on stoke,其他值映射为 null
  • 找到缺货的missing-codes=代码,就像第一个甚至没有代码10一样,并制作缺货和qty=0的文档
  • concat 在 Stock 中找到代码和缺少代码
  • 展开并替换根目录

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

【讨论】:

  • 我正在使用 2kk 文档在我的收藏中运行您的答案。
  • 成功了,用了 3 分钟的火花!非常感谢!
  • 我又尝试了一个查询,如果您看到这个,不妨试试并发送一些反馈,哪个更快。
  • 是否也可以在输出中设置Stock.Qty
  • 我又添加了一个查询,以保存数量并且您在结果中看到它,我认为这就是您所说的设置,如果您想更改数量,您也可以这样做,但是我想你的意思是保留他们的数量。
猜你喜欢
  • 2019-05-20
  • 1970-01-01
  • 2013-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多