如何编写查找多个路径的 MongoDB 查询

Vla*_*kic 5 mongodb mongodb-query nosql-aggregation aggregation-framework

这是我正在使用的集合:

- sign1: A1
- sign2: A2

- sign1: A2
- sign2: A5

- sign1: A2
- sign2: A6

- sign1: A2
- sign2: A8

- sign1: A5
- sign2: A8
Run Code Online (Sandbox Code Playgroud)

查询应该找到从 A1 到 A8 的路径

例如,它应该找到:

path1:
A1 A2 -> A2 A5 -> A5 A8

path2:
A1 A2 -> A2 A8

path3:
A1 A2 -> A2 A6 -> should be ignored since not finishes with A8
Run Code Online (Sandbox Code Playgroud)

目前,我尝试了这个(@ray 的部分解决方案):

我的查询

我的查询的第一个问题是它返回所有路径,即使它不以 A8 结尾

第二个问题是不分离路径将所有内容放在一个数组中

dev*_*exe 0

要过滤并仅返回以您结尾的路径,则A8必须在. $graphLookup

您可以尝试类似的方法来仅返回以以下结尾的路径A8

db.collection.aggregate([
  {
    "$match": {
      sign1: "A1"
    }
  },
  {
    "$graphLookup": {
      "from": "collection",
      "startWith": "$sign1",
      "connectFromField": "sign2",
      "connectToField": "sign1",
      "as": "path",
      "depthField": "step"
    }
  },
  {
    "$match": {
      "path.sign2": "A8"
    }
  }
])
Run Code Online (Sandbox Code Playgroud)

现在,如果您想将路径分成不同的数组/文档,您必须在该阶段之前使用$unwind 阶段,$match如下所示:

db.collection.aggregate([
  {
    "$match": {
      sign1: "A1"
    }
  },
  {
    "$graphLookup": {
      "from": "collection",
      "startWith": "$sign1",
      "connectFromField": "sign2",
      "connectToField": "sign1",
      "as": "path",
      "depthField": "step"
    }
  },
  {
    "$unwind": "$path"
  },
  {
    "$match": {
      "path.sign2": "A8"
    }
  }
])
Run Code Online (Sandbox Code Playgroud)

编辑:如果您想过滤不需要的路径或等于step0 的路径,您可以$filter在$graphLookup阶段中使用如下操作,根据这两个条件返回结果。

db.collection.aggregate([
  {
    "$match": {
      sign1: "A1"
    }
  },
  {
    "$graphLookup": {
      "from": "collection",
      "startWith": "$sign1",
      "connectFromField": "sign2",
      "connectToField": "sign1",
      "as": "path",
      "depthField": "step",
      "maxDepth": 10,
      "filter": {
        "$and": [
          { "step": { "$gt": 0 } },
          { "sign2": "A8" }
        ]
      }
    }
  },
  {
    "$unwind": "$path"
  }
])

Run Code Online (Sandbox Code Playgroud)