【问题标题】:mongodb update/upsert and nested arraysmongodb update/upsert 和嵌套数组
【发布时间】:2021-10-31 03:39:27
【问题描述】:

我有一个集合,其中包含有关我网站上的会议和用户的指标,我想按会议存储它们。每个会议有一个或多个用户,每个用户有一个或多个会话,每个会话有一个或多个指标。

这是我要保存的会议文档示例:

{
    "conf":"conference12345",
    "users":[
        { //User 1
            "uid":"2dd8b4e3-9dcd-4da6-bc36-aa0988dc9642",
            "sessions":[
                [// User 1 => session 1
                    {
                        "ts": 1234567891,
                        "br":"Chrome 92",
                        "os":"Windows",
                    },
                    {
                        "ts": 1234567899,
                        "bw":100
                    }
                ],
                [// User 1 => session 2
                    {
                        "ts": 1234567900,
                        "br":"Chrome 92",
                        "os":"Windows",
                    },
                    {
                        "ts": 1234567950,
                        "bw":500
                    }
                ],
            ]
        },
        { //User 2
            "uid":"2dd8b4e3-9dcd-4da6-bc36-aa0988dc9666",
            "sessions":[
                [// User 2 => session 1
                    {
                        "ts": 1234567891,
                        "br":"Chrome 90",
                        "os":"Mac",
                    },
                    {
                        "ts": 1234567899,
                        "bw":100
                    }
                ]
            ]
        }
    ]
}

我想通过使用db.collection.updateupsert 选项来一次插入新数据。但我很难弄清楚怎么做。指标应添加到“会话”数组的最后一个元素。

这是我要添加的数据示例:

// New user. a new document should be created because it's a new conference.
{ 
        "conf": "conferenceXYZ",
        "uid": "1cd8b4e3-9dcd-4da6-bc36-aa0988dc9512",
        "metrics": {
                "ts": 1234567891,
                "br":"Chrome 90",
                "os":"Mac",
        }
}

// Existing user. metrics should be added to his last session
{ 
        "conf": "conference12345",
        "uid": "2dd8b4e3-9dcd-4da6-bc36-aa0988dc9642",
        "metrics": {
                "ts": 1234567891,
                "bw":356
        }
}

我尝试使用带有 upsert 选项的更新,但很难找到丢失的部分。任何帮助将不胜感激。

【问题讨论】:

    标签: arrays mongodb upsert mongodb-update


    【解决方案1】:

    查询

    • 第一个过滤器/$set是放你的数据
    • 检查是否有新用户(其新用户以防更新插入或未找到用户)
    • 如果新用户推送新用户 else 找到用户并添加新会话
    db.collection.update({
      "conf": "conference12345"
    },
    [
      {
        "$set": {
          "uid": "2dd8b4e3-9dcd-4da6-bc36-aa0988dc9642",
          "usession": {
            "ts": 1234567891,
            "bw": 356
          }
        }
      },
      {
        "$set": {
          "new-user": {
            "$eq": [
              {
                "$filter": {
                  "input": {
                    "$cond": [
                      "$users",
                      "$users",
                      []
                    ]
                  },
                  "as": "u",
                  "cond": {
                    "$eq": [
                      "$$u.uid",
                      "$uid"
                    ]
                  }
                }
              },
              []
            ]
          }
        }
      },
      {
        "$set": {
          "users": {
            "$cond": [
              "$new-user",
              {
                "$concatArrays": [
                  {
                    "$cond": [
                      {
                        "$isArray": [
                          "$users"
                        ]
                      },
                      "$users",
                      []
                    ]
                  },
                  [
                    {
                      "uid": "$uid",
                      "sessions": [
                        [
                          "$usession"
                        ]
                      ]
                    }
                  ]
                ]
              },
              {
                "$map": {
                  "input": "$users",
                  "as": "u",
                  "in": {
                    "$cond": [
                      {
                        "$eq": [
                          "$$u.uid",
                          "$uid"
                        ]
                      },
                      {
                        "$mergeObjects": [
                          "$$u",
                          {
                            "sessions": {
                              "$let": {
                                "vars": {
                                  "last_index": {
                                    "$subtract": [
                                      {
                                        "$size": "$$u.sessions"
                                      },
                                      1
                                    ]
                                  }
                                },
                                "in": {
                                  "$cond": [
                                    {
                                      "$or": [
                                        "$usession.br",
                                        {
                                          "$eq": [
                                            "$$last_index",
                                            -1
                                          ]
                                        }
                                      ]
                                    },
                                    {
                                      "$concatArrays": [
                                        "$$u.sessions",
                                        [
                                          [
                                            "$usession"
                                          ]
                                        ]
                                      ]
                                    },
                                    {
                                      "$let": {
                                        "vars": {
                                          "last_session": {
                                            "$arrayElemAt": [
                                              "$$u.sessions",
                                              "$$last_index"
                                            ]
                                          }
                                        },
                                        "in": {
                                          "$concatArrays": [
                                            {
                                              "$slice": [
                                                "$$u.sessions",
                                                0,
                                                "$$last_index"
                                              ]
                                            },
                                            [
                                              {
                                                "$concatArrays": [
                                                  "$$last_session",
                                                  [
                                                    "$usession"
                                                  ]
                                                ]
                                              }
                                            ]
                                          ]
                                        }
                                      }
                                    }
                                  ]
                                }
                              }
                            }
                          }
                        ]
                      },
                      "$$u"
                    ]
                  }
                }
              }
            ]
          }
        }
      },
      {
        "$unset": [
          "uid",
          "usession",
          "new-user"
        ]
      }
    ],
    {
      "upsert": true
    })
    

    【讨论】:

    • 感谢您的建议。应稍微编辑此查询以在 sessions 数组的最后一个元素中添加指标。如果度量对象包含bros 元素,则应创建一个新的会话元素
    • 上述查询总是在会话数组中添加新的指标对象。它永远不会与现有指标合并,您还想更新现有指标吗?基于什么标准?同样ts?最好写下所有案例以及您希望在每种情况下发生什么,我编写了查询检查的案例,如果您有更多案例,请扩展这些案例。
    • 感谢您花时间考虑这个问题。这是我的修改mongoplayground.net/p/ghiWD3Cm2wy。除非该指标包含br,否则新指标必须进入最后一个会话数组,这意味着应在会话数组中创建一个新数组
    • 我又添加了一个案例,如果 br 创建新数组,否则在最后一个会话中推送它。希望这次对你有用,查询很大,但它的简单 JSON 使它更难阅读但没关系
    • 这是一项很棒的工作。谢谢
    猜你喜欢
    • 2021-06-17
    • 2017-07-26
    • 1970-01-01
    • 2020-11-09
    • 1970-01-01
    • 2014-05-05
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多