在 MongoDB 中获取子数组中的上一个和下一个

Get previous and next inside sub array in MongoDB

我有如下数据库。

[
    {
        "title": "Data 1",
        "slug": "data-1",
        "sub_docs": [
            {
                "name": "Sub Doc 1",
                "sub_slug": "sub-doc-1",
                "urls": [
                    "https://example.com/path-1",
                ]
            },
            {
                "name": "Sub Doc 2",
                "sub_slug": "sub-doc-2",
                "urls": [
                    "https://example.com/path-2"
                ]
            },
            {
                "name": "Sub Doc 3",
                "sub_slug": "sub-doc-3",
                "urls": [
                    "https://example.com/path-3",
                ]
            }
        ]
    }
]

当我将 data-1 和 sub-doc-2 作为输入时,我想得到以下结果。

{
    "title": "Data 1",
    "sub_doc_title": "Sub Doc 2",
    "urls": [
        "https://example.com/path-2"
    ],
    "prev": {
        "name": "Sub Doc 1",
        "sub_slug": "sub-doc-1"
    },
    "next": {
        "name": "Sub Doc 3",
        "sub_slug": "sub-doc-3"
    }
}

我是 MongoDB 的新手。 我该如何做这个查询?你有什么想法吗?

这对初学者来说是一个艰难的问题,虽然我仍然认为自己是新手,所以也许有 better/easy 方法。

这是您可以做到的一种方法。

db.collection.aggregate([
  {
    "$match": {
      "slug": "data-1"  // given argument
    }
  },
  {
    "$set": {
      "reduceOut": {
        "$reduce": {
          "input": "$sub_docs",
          "initialValue": {
            "sub_doc_title": null,
            "urls": [],
            "prev": null,
            "next": null
          },
          "in": {
            "$cond": [
              {
                "$eq": [
                  "$$this.sub_slug",
                  "sub-doc-2"         // given argument
                ]
              },
              {
                "$mergeObjects": [
                  "$$value",
                  {
                    "sub_doc_title": "$$this.name",
                    "urls": "$$this.urls"
                  }
                ]
              },
              {
                "$cond": [
                  { "$eq": [ "$$value.sub_doc_title", null ] },
                  {
                    "$mergeObjects": [
                      "$$value",
                      {
                        "prev": {
                          "name": "$$this.name",
                          "sub_slug": "$$this.sub_slug"
                        }
                      }
                    ]
                  },
                  {
                    "$cond": [
                      { "$eq": [ "$$value.next", null ] },
                      {
                        "$mergeObjects": [
                          "$$value",
                          {
                            "next": {
                              "name": "$$this.name",
                              "sub_slug": "$$this.sub_slug"
                            }
                          }
                        ]
                      },
                      "$$value"
                    ]
                  }
                ]
              }
            ]
          }
        }
      }
    }
  },
  {
    "$replaceWith": {
      "$mergeObjects": [
        {
          "title": "$title"
        },
        "$reduceOut"
      ]
    }
  }
])

mongoplayground.net 上试用。

感谢 rickhg12hs 的回答。我也找到了这个问题的解决方案。

这是我的答案;

db.collection.aggregate([
  {
    "$match": {
      "slug": "data-1"
    }
  },
  {
    "$addFields": {
      "sub_doc_index": {
        "$indexOfArray": [
          "$sub_docs.sub_slug",
          "sub-doc-2"
        ]
      }
    }
  },
  {
    "$project": {
      "title": 1,
      "sub_doc_title": {
        "$arrayElemAt": [
          "$sub_docs.name",
          "$sub_doc_index"
        ]
      },
      "urls": {
        "$arrayElemAt": [
          "$sub_docs.urls",
          "$sub_doc_index"
        ]
      },
      "prev": {
        "$cond": {
          "if": {
            "$eq": [
              {
                "$subtract": [
                  "$sub_doc_index",
                  1
                ]
              },
              -1
            ]
          },
          "then": {},
          "else": {
            "name": {
              "$arrayElemAt": [
                "$sub_docs.name",
                {
                  "$subtract": [
                    "$sub_doc_index",
                    1
                  ]
                }
              ]
            },
            "slug": {
              "$arrayElemAt": [
                "$sub_docs.sub_slug",
                {
                  "$subtract": [
                    "$sub_doc_index",
                    1
                  ]
                }
              ]
            }
          },
          
        },
        
      },
      "next": {
        "name": {
          "$arrayElemAt": [
            "$sub_docs.name",
            {
              "$add": [
                "$sub_doc_index",
                1
              ]
            }
          ]
        },
        "slug": {
          "$arrayElemAt": [
            "$sub_docs.sub_slug",
            {
              "$add": [
                "$sub_doc_index",
                1
              ]
            }
          ]
        }
      }
    }
  },
  
])