uni-app 聚合阶段的geoNear无法获取到符合条件的全部数据

uni-app 聚合阶段的geoNear无法获取到符合条件的全部数据 产品分类:
uniCloud/腾讯云

App下载地址或H5网址:
www.xnkj.ren

示例代码:

console.log(`--- 附近 ---`);  
let {locData} = self,  
    {longitude, latitude} = locData,  
    query = {  
        deleted: _.neq(true), // 未删除  
        offShelves: _.neq(true), // 未下架  
        "community.0.public": _.neq(false) // 公开  
    };  
if(unrefresh){  
    let gots = [];  
    list.forEach( x => gots.push(x._id));  
    console.log({gots});  
    query._id = _.nin(gots);  
};  
let geoNear = {  
        distanceField: 'distance',  
        maxDistance: 100000,  
        minDistance: 0,  
        spherical: true,  
        near: new db.Geo.Point(longitude, latitude),  
        key: "geoPoint"  
    },  
    dyn = {  
        ...query,  
        type: "dynamic"  
    },  
    que = {  
        ...query,  
        type: "question",  
    },  
    reso = {  
        ...query,  
        type: "resource",  
    },  
    tas = {  
        ...query,  
        type: "task",  
        taskData: {  
            progress: _.or([_.exists(false), _.size(0)]), // 未被接  
            "order.0.paid": true, // 已支付押金  
            repealed: _.neq(true) // 未撤销  
        }  
    },  
    query1;  
if(keyword == "推荐"){  
    query1 = _.or([dyn, que, reso, tas]);  
}else if(keyword == "动态"){  
    query1 = dyn;  
}else if(keyword == "问题"){  
    query1 = que;  
}else if(keyword == "资源"){  
    query1 = reso;  
}else if(keyword == "任务"){  
    query1 = tas;  
};  
db.collection('xn-user-action').aggregate().geoNear(geoNear).lookup({  
    from: 'uni-id-users',  
    let: {  
        creator: '$creatorID',  
    },  
    pipeline: $.pipeline().match(_.expr($.eq(['$_id','$$creator']))).project({avatar_file:1, nickname:1}).done(),  
    as: 'creatorID'  
}).lookup({  
    from: 'xn-community',  
    let: {  
        id: '$communityID',  
    },  
    pipeline: $.pipeline().match(_.expr($.eq(['$_id','$$id']))).project({public:1, name:1}).done(),  
    as: 'community'  
}).lookup({  
    from: "xn-order",  
    let: {  
        orderID: "$taskData.orderID"  
    },  
    pipeline: $.pipeline().match(_.expr($.eq(['$orderID', '$$orderID']))).project({paid: 1}).done(),  
    as: 'taskData.order'  
})  
.match(query1)  
.sort({creatTime: -1})  
.limit(20)  
.end().then(({result:{data:newList}})=>{  
    console.log(`一共${newList.length}条数据`);  
    resolve(newList);  
    newList.forEach(x=> handleData(x));  
    if(unrefresh){  
        action.list = list.concat(newList);  
    }else action.list = newList;  
    if(newList.length < 20){  
        self.$nextTick().then(()=>{  
            action.status = 'nomore';  
        });  
    }else{  
        self.$nextTick().then(()=>{  
            action.status = 'loadmore';  
        });  
    };  
}).catch(err=>{  
    console.log(err)  
    reject(err);  
})
7 回复

我看你的sort使用的是createTime,在数据库的20条数据能按照这个做出唯一排序吗?


我把sort去掉也是一样的,甚至切换一下定位后,一条数据都获取不到了

回复 1***@qq.com: 整理个简单的示例发一下吧

回复 DCloud_uniCloud_WYQ: 就是复杂聚合查询,无法按照预期获取到数据

回复 1***@qq.com: 地理位置查询

回复 1***@qq.com: 导出一份db_init.json,以及对应的有问题的聚合查询,其中不要出现变量

在使用 uni-app 进行 MongoDB 聚合查询时,如果你发现 geoNear 阶段无法获取到符合条件的全部数据,可能有以下几个原因和解决方法:

1. 检查集合是否有2d或2dsphere索引

  • geoNear 阶段要求集合必须有一个 2d2dsphere 索引。如果没有创建相应的索引,geoNear 将无法正常工作。
  • 确保你在目标集合上创建了正确的索引。例如:
    db.collection.createIndex({ location: "2dsphere" });

2. 检查坐标数据的格式

  • geoNear 要求地理位置数据的格式必须符合 MongoDB 的地理空间数据类型。通常,坐标数据应该是一个包含 typecoordinates 的 GeoJSON 对象。
  • 例如:
    {
      "location": {
        "type": "Point",
        "coordinates": [longitude, latitude]
      }
    }

3. 检查查询范围

  • geoNear 默认会返回距离查询点最近的 100 个文档。如果你需要获取更多的数据,可以通过 limit 参数来调整返回的文档数量。
  • 例如:
    db.collection.aggregate([
      {
        $geoNear: {
          near: { type: "Point", coordinates: [longitude, latitude] },
          distanceField: "distance",
          maxDistance: 10000, // 最大距离(单位:米)
          spherical: true,
          limit: 1000 // 返回最多 1000 个文档
        }
      }
    ]);

4. 检查 maxDistance 参数

  • maxDistance 参数用于限制查询的最大距离。如果 maxDistance 设置得太小,可能会导致返回的文档数量不足。
  • 确保 maxDistance 设置合理,或者不设置该参数以获取所有符合条件的文档。

5. 检查 spherical 参数

  • 如果你使用的是 2dsphere 索引,确保将 spherical 参数设置为 true,以启用球面几何计算。
  • 例如:
    db.collection.aggregate([
      {
        $geoNear: {
          near: { type: "Point", coordinates: [longitude, latitude] },
          distanceField: "distance",
          spherical: true
        }
      }
    ]);

6. 检查数据是否在查询范围内

  • 确保你的数据确实在查询范围内。如果数据不在查询范围内,geoNear 将无法返回任何结果。

7. 检查聚合管道的其他阶段

  • 如果 geoNear 阶段后面还有其他聚合阶段(如 $match$project 等),确保这些阶段没有过滤掉你需要的文档。

8. 调试和日志

  • 使用 console.log 或调试工具检查聚合管道的每个阶段的输出,确保数据在管道中正确传递。

示例代码

以下是一个完整的 geoNear 聚合查询示例:

db.collection.aggregate([
  {
    $geoNear: {
      near: { type: "Point", coordinates: [longitude, latitude] },
      distanceField: "distance",
      maxDistance: 10000, // 最大距离(单位:米)
      spherical: true,
      limit: 1000 // 返回最多 1000 个文档
    }
  }
]);
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!