【问题标题】:MongoDB - Limit the number of elements in array based on type (max N elements for each type)MongoDB - 根据类型限制数组中的元素数量(每种类型最多 N 个元素)
【发布时间】:2021-12-27 16:45:08
【问题描述】:

我想创建一个查询,将每个 entityType 的元素数限制为最大 N=2

除了entityType & entityId,原始文档还有一些其他属性(例如:timestamp),为了简单起见,我只是将其删除。

这是初始/参考文档。

{
    "_id" : ObjectId("100000"),
    "agency" : "agency_1",
    "username" : "user_one",
    "recentEntities" : {
        "entities" : [ 
            {
                "entityType" : "type_one",
                "entityId" : "11",
                "other" : "aa",
            },
            {
                "entityType" : "type_one",
                "entityId" : "12",
                "other" : "ab",
            },
            {
                "entityType" : "type_two",
                "entityId" : "21",
                "other" : "ba",
            }
        ]
    }
}

这里是这个问题的 3 个规范/案例:

  • 每次添加一个新实体作为entities 数组中的第一个 元素时,表示最近可见的实体。

假设我想用以下实体更新初始文档:

{
    "entityType" : "type_two",
    "entityId" : "22",
    "other" : "bb",
}

由于我们没有达到"entityType" = "type_two" 的限制,我们只需将对象添加到数组中,更新后的文档将如下所示:

{
    "_id" : ObjectId("100000"),
    "agency" : "agency_1",
    "username" : "user_one",
    "recentEntities" : {
        "entities" : [ 
            {
                "entityType" : "type_two",
                "entityId" : "22",
                "other" : "bb",
            },
            {
                "entityType" : "type_one",
                "entityId" : "11",
                "other" : "aa",
            },
            {
                "entityType" : "type_one",
                "entityId" : "12",
                "other" : "ab",
            },
            {
                "entityType" : "type_two",
                "entityId" : "21",
                "other" : "ba",
            }
        ]
    }
}
  • 如果带有特定entityId 的文档已经存在,但对象内的其他字段已更改,那么我想将该实体对象替换为最近的。

使用此实体更新 reference 文档:

{
    "entityType" : "type_one",
    "entityId" : "12",
    "other" : "xy",
}

将导致:

{
    "_id" : ObjectId("100000"),
    "agency" : "agency_1",
    "username" : "user_one",
    "recentEntities" : {
        "entities" : [ 
            {
                "entityType" : "type_one",
                "entityId" : "12",
                "other" : "xy",
            },
            {
                "entityType" : "type_one",
                "entityId" : "11",
                "other" : "aa",
            },
            {
                "entityType" : "type_two",
                "entityId" : "21",
                "other" : "ba",
            }
        ]
    }
}
  • 另一方面,如果已达到限制,则将删除特定类型的最旧实体。

例如通过添加以下实体:

{
    "entityType" : "type_one",
    "entityId" : "13",
    "other" : "ac",
}

我们需要删除 "entityId" = "12" 并将新的放在上面。

更新后,参考文档将如下所示:

{
    "_id" : ObjectId("100000"),
    "agency" : "agency_1",
    "username" : "user_one",
    "recentEntities" : {
        "entities" : [ 
            {
                "entityType" : "type_one",
                "entityId" : "13",
                "other" : "ac",
            },
            {
                "entityType" : "type_one",
                "entityId" : "11",
                "other" : "aa",
            },
            {
                "entityType" : "type_two",
                "entityId" : "21",
                "other" : "ba",
            }
        ]
    }
}

我设法做到了前 2 点,但最后一点实施起来有点棘手,因此非常感谢任何帮助。

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    您可以在聚合管道中执行以下操作:

    1. 使用$concatArrays将最新条目(即entityId 13)附加到数组中
    2. $unwind 带有 includeArrayIndex 选项的数组。我将索引命名为idx
    3. $sortidx: -1
    4. $limit 按您想要的计数(即您的示例中的 3)
    5. $group 又是$push 的实体
    db.collection.aggregate([
      {
        "$match": {
          "_id": "100000"
        }
      },
      {
        "$addFields": {
          "recentEntities.entities": {
            "$concatArrays": [
              "$recentEntities.entities",
              [
                {
                  "entityType": "type_one",
                  "entityId": "13",
                  "other": "ac",
                  
                }
              ]
            ]
          }
        }
      },
      {
        "$unwind": {
          path: "$recentEntities.entities",
          includeArrayIndex: "idx"
        }
      },
      {
        "$sort": {
          idx: -1
        }
      },
      {
        $limit: 3
      },
      {
        "$sort": {
          idx: 1
        }
      },
      {
        $group: {
          _id: "$_id",
          "agency": {
            $first: "$agency"
          },
          "username": {
            $first: "$username"
          },
          "re": {
            $push: "$recentEntities.entities"
          }
        }
      },
      {
        "$project": {
          "agency": 1,
          "username": 1,
          "recentEntities": {
            entities: "$re"
          }
        }
      }
    ])
    

    这是Mongo playground 供您参考。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-04
      • 2018-03-01
      • 1970-01-01
      • 2015-08-06
      • 1970-01-01
      • 1970-01-01
      • 2017-08-01
      • 1970-01-01
      相关资源
      最近更新 更多