首页 > 解决方案 > $lookup 后如何使用 $geoNear

问题描述

您好我有以下问题:我想使用 $geoNear (计算两点之间的距离)但在 $loopback 之后(以及我加入的集合)。这是 companyBases 集合的模型(我想加入它):

{
    "_id" : ObjectId("5d7cfe13f42e7345d967b378"),
    "location" : {
        "type" : "Point",
        "coordinates" : [
            20.633856,
            49.761268
        ]
    },
    "vehicles" : [
        {
            "_id" : ObjectId("5d7cfe13f42e7345d967b340"),
            ...other fields that doesn't matter
        }
    ]
}

这是车辆集合:

{
            "_id" : ObjectId("5d7cfe13f42e7345d967b340"),
            ...other fields that doesn't matter
}

我想加入 companyBase 集合以汇总车辆集合:

db.vehicles.aggregate([
  {
    $lookup: {
      from: "companybases",
      let: {
        vehicleId: "$_id"
      },
      pipeline: [
        {
          $match: {
            $expr: { $in: ["$$vehicleId", "$vehicles._id"] }
          }
        }
      ],
      as: "companyBases"
    }
  },
  {
    $unwind: "$companyBases"
  },
  {
    $geoNear: {
      near: {
        type: "Point",
        coordinates: [50.02485, 20.0008]
      },
      distanceField: "distance",
      spherical: true
    }
  }
]);


但它返回给我:

{
    "message" : "$geoNear is only valid as the first stage in a pipeline.",
    "operationTime" : "Timestamp(1568472833, 1)",
    "ok" : 0,
    "code" : 40602,
    "codeName" : "Location40602",
    "$clusterTime" : {
        "clusterTime" : "Timestamp(1568472833, 1)",
        "signature" : {
            "hash" : "AAAAAAAAAAAAAAAAAAAAAAAAAAA=",
            "keyId" : "0"
        }
    },
    "name" : "MongoError"
}

当我在 companybases 集合上执行相同的管道时,它会返回具有计数距离的文档:

db.companybases.aggregate([
  {
    $geoNear: {
      near: {
        type: "Point",
        coordinates: [50.02485, 20.0008]
      },
      distanceField: "distance",
      spherical: true
    }
  }
]);

结果:

{
    "_id" : ObjectId("5d7cfe13f42e7345d967b378"),
    "location" : {
        "type" : "Point",
        "coordinates" : [
            20.633856,
            49.761268
        ]
    },
    "vehicles" : [
        {
            ...some fields
        },

    ],
    ...some fields
    "distance" : 4209673.447019393
}

我意识到错误可能是由于车辆收集上缺少索引。那么有什么方法可以用 $geoNear 和 $lookup 计算距离吗?或者也许这是不可能的,我必须自己做?

标签: mongodbnosql

解决方案


简单的解决方案(您可以将 $geoNear 放入 $lookup 管道中):

db.vehicles.aggregate([
  {
    $lookup: {
      from: "companybases",
      let: {
        vehicleId: "$_id"
      },
      pipeline: [
        {
          $geoNear: {
            near: {
              type: "Point",
              coordinates: [50.02485, 20.0008]
            },
            distanceField: "distance",
            spherical: true
          }
        },
        {
          $match: {
            $expr: { $in: ["$$vehicleId", "$vehicles._id"] }
          }
        }
      ],
      as: "companyBases"
    }
  },
  {
    $unwind: "$companyBases"
  }
]);

但这给性能留下了深刻的印象(至少需要 5 秒),因为在比赛前使用了 $geoNear。


推荐阅读