2

我正在尝试找到一种方法来创建一个引擎,该引擎将 GraphQL 查询过滤器转换为 MongoDB 聚合,同时保持性能。我们的应用程序需要通过对集合 B、C 甚至 D 应用过滤器来限制集合 A 的结果。

为了更好地理解,这里有一个关于如何将过滤器转换为 MongoDB 的示例。

这个:

{
  "filter": {
    "return": null,
    "AND": [{
      "customer_WITH": {
        "OR": [{
          "code": "CUSTOMER NAME"
        }, {
          "commercialName_LIKE": "CUSTOMER NAME"
        }, {
          "corporateName_LIKE": "CUSTOMER NAME"
        }]
      }
    }],
    "OR": [{
      "dispatcher_WITH": {
        "company_WITH": {
          "corporateName_LIKE": "COMPANY NAME"
        }
      }
    }, {
      "redispatcher_WITH": {
        "company_WITH": {
          "corporateName_LIKE": "COMPANY NAME"
        }
      }
    }],
    "reversal": null
  }
}

被翻译成这样:

[{
  "$match": {
    "return": {
      "$eq": null
    },
    "reversal": {
      "$eq": null
    },
    "company": {
      "$eq": ObjectId("xxxxxxxxxxxxxxxxxxxxxxxx")
    }
  }
}, {
  "$lookup": {
    "as": "dispatcher",
    "from": "shippers",
    "localField": "dispatcher",
    "foreignField": "_id"
  }
}, {
  "$unwind": {
    "path": "$dispatcher",
    "preserveNullAndEmptyArrays": true
  }
}, {
  "$lookup": {
    "as": "dispatcher.company",
    "from": "companies",
    "localField": "dispatcher.company",
    "foreignField": "_id"
  }
}, {
  "$unwind": {
    "path": "$dispatcher.company",
    "preserveNullAndEmptyArrays": true
  }
}, {
  "$lookup": {
    "as": "redispatcher",
    "from": "shippers",
    "localField": "redispatcher",
    "foreignField": "_id"
  }
}, {
  "$unwind": {
    "path": "$redispatcher",
    "preserveNullAndEmptyArrays": true
  }
}, {
  "$lookup": {
    "as": "redispatcher.company",
    "from": "companies",
    "localField": "redispatcher.company",
    "foreignField": "_id"
  }
}, {
  "$unwind": {
    "path": "$redispatcher.company",
    "preserveNullAndEmptyArrays": true
  }
}, {
  "$lookup": {
    "as": "customer",
    "from": "customers",
    "localField": "customer",
    "foreignField": "_id"
  }
}, {
  "$match": {
    "$or": [{
      "dispatcher.company.corporateName": {
        "$regex": /\sCOMPANY\sNAME/
      }
    }, {
      "redispatcher.company.corporateName": {
        "$regex": /\sCOMPANY\sNAME/
      }
    }],
    "$and": [{
      "$or": [{
        "customer.code": {
          "$eq": "CUSTOMER NAME"
        }
      }, {
        "customer.commercialName": {
          "$regex": /CUSTOMER\sNAME/
        }
      }, {
        "customer.corporateName": {
          "$regex": /CUSTOMER\sNAME/
        }
      }]
    }]
  }
}, {
  "$unwind": {
    "path": "$customer",
    "preserveNullAndEmptyArrays": true
  }
}, {
  "$group": {
    "_id": "$invoiceNo",
    "__rootId": {
      "$first": "$_id"
    },
    "company": {
      "$first": "$company"
    },
    "customer": {
      "$first": "$customer._id"
    },
    "dispatcher": {
      "$first": "$dispatcher._id"
    },
    "redispatcher": {
      "$first": "$redispatcher._id"
    },
    "driverPlate": {
      "$first": "$driverPlate"
    },
    "key": {
      "$first": "$key"
    },
    "activities": {
      "$first": "$activities"
    },
    "serialNo": {
      "$first": "$serialNo"
    },
    "invoiceNo": {
      "$first": "$invoiceNo"
    },
    "incidents": {
      "$first": "$incidents"
    },
    "deliveries": {
      "$first": "$deliveries"
    },
    "return": {
      "$first": "$return"
    }
  }
}, {
  "$project": {
    "_id": "$__rootId",
    "company": "$company",
    "customer": "$customer",
    "dispatcher": "$dispatcher",
    "redispatcher": "$redispatcher",
    "driverPlate": "$driverPlate",
    "key": "$key",
    "activities": "$activities",
    "serialNo": "$serialNo",
    "invoiceNo": "$invoiceNo",
    "incidents": "$incidents",
    "deliveries": "$deliveries",
    "return": "$return"
  }
}, {
  "$sort": {
    "invoiceNo": -1
  }
}, {
  "$limit": 51
}]

该引擎足够聪明,可以重新分配到不需要 $lookups 的第一个位置 $match 属性,如果需要,则在 $lookups 之后立即重新分配,但是如果它们在 $and/$or 条件块内,则在最后 $lookup,不管那里有什么属性。

我可以扫描 $and 中使用的内容并将其解构为新的重新分配的 $match 阶段,但我需要弄清楚如何处理 $or 运算符:我不能对其应用相同的解构想法,因为这会使健康)状况。

所以我的问题是:是否有另一种方法可以将阶段 $lookup 与 $and/$or 一起使用并大幅提高性能?

创建更多索引无济于事,因为它们不用于 $lookup。正如 MongoDB 团队建议的那样,向上移动 $match 阶段也是不可能的,因为它会破坏条件。所以我现在没有主意了。

此致。

4

0 回答 0