Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 查找最接近的用户而无需遍历多个记录_Swift_Firebase_Google Cloud Firestore - Fatal编程技术网

Swift 查找最接近的用户而无需遍历多个记录

Swift 查找最接近的用户而无需遍历多个记录,swift,firebase,google-cloud-firestore,Swift,Firebase,Google Cloud Firestore,当用户登录到我的应用程序时,我希望他们能够看到选定半径内的用户数。我计划开始在数据库中存储坐标,并循环遍历每个记录(~50000),运行userCoordinates.distance(from:databaseCoordinateValue)。然而,在测试过程中,我发现这个过程需要很长时间,并且不是一个可伸缩的解决方案。对于如何快速查询定义半径内的数据库项,您有什么建议吗 我正在使用: 斯威夫特4 Firebase(Firestore测试版) Xcode 10 数据库结构和数据存储方式示例

当用户登录到我的应用程序时,我希望他们能够看到选定半径内的用户数。我计划开始在数据库中存储坐标,并循环遍历每个记录(~50000),运行userCoordinates.distance(from:databaseCoordinateValue)。然而,在测试过程中,我发现这个过程需要很长时间,并且不是一个可伸缩的解决方案。对于如何快速查询定义半径内的数据库项,您有什么建议吗

我正在使用:

  • 斯威夫特4
  • Firebase(Firestore测试版)
  • Xcode 10
数据库结构和数据存储方式示例

 database.collection("users").document((Auth.auth().currentUser?.uid)!).setData([
                "available_tags" : ["milk", "honey"]]) { err in
                if let err = err {
                    print("Error adding document: \(err)")
                }
             }

看看s2几何体-。基本概念是将地球上的每个位置编码为64位,彼此靠近的位置是接近的。然后,您可以通过查找距离该位置+/-某个#的任何内容来查找x距离内的位置。现在,实际的实现有点复杂,因此您最终需要创建多个“单元”,即范围上的最小值和最大值。然后,查找每个单元格。(更多信息请访问。)

下面是在node.js/javascript中执行此操作的示例。我在后端使用它,让前端只通过区域/区域

    const S2 = require("node-s2");

    static async getUsersInRegion(region) {
    // create a region
    const s2RegionRect = new S2.S2LatLngRect(
      new S2.S2LatLng(region.NECorner.latitude, region.NECorner.longitude),
      new S2.S2LatLng(region.SWCorner.latitude, region.SWCorner.longitude),
    );

    // find the cell that will cover the requested region
    const coveringCells = S2.getCoverSync(s2RegionRect, { max_cells: 4 });

    // query all the users in each covering region/range simultaneously/in parallel
    const coveringCellQueriesPromies = coveringCells.map(coveringCell => {
      const cellMaxID = coveringCell
        .id()
        .rangeMax()
        .id();
      const cellMinID = coveringCell
        .id()
        .rangeMin()
        .id();

      return firestore
        .collection("User")
        .where("geoHash", "<=", cellMaxID)
        .where("geoHash", ">=", cellMinID).
        get();
    });

    // wait for all the queries to return
    const userQueriesResult = await Promise.all(coveringCellQueriesPromies);

    // create a set of users in the region
    const users = [];

    // iterate through each cell and each user in it to find those in the range
    userQueriesResult.forEach(userInCoveringCellQueryResult => {
      userInCoveringCellQueryResult.forEach(userResult => {
        // create a cell id from the has
        const user = userResult.data();
        const s2CellId = new S2.S2CellId(user.geoHash.toString());
        // validate that the user is in the view region
        // since cells will have areas outside of the input region
        if (s2RegionRect.contains(s2CellId.toLatLng())) {
          user.id = userResult.id;
          users.push(user);
        }
      });
    });

    return users;
  }
const S2=require(“节点-S2”);
静态异步getUsersInRegion(区域){
//创建一个区域
const s2RegionRect=新的S2.S2LatLngRect(
新的S2.S2LatLng(region.NECorner.lations,region.NECorner.lations),
新S2.S2LatLng(region.SWCorner.lation,region.SWCorner.longitude),
);
//查找将覆盖请求区域的单元格
const coveringCells=S2.getCoverSync(s2RegionRect,{max_cells:4});
//同时/并行查询每个覆盖区域/范围内的所有用户
const coveringCellQueriesPromies=coveringCells.map(coveringCell=>{
const cellMaxID=coveringCell
.id()
.rangeMax()
.id();
const cellMinID=覆盖单元
.id()
.rangeMin()
.id();
返回火库
.收集(“用户”)
.where(“geoHash”,“=”,cellMinID)。
get();
});
//等待所有查询返回
const userQueriesResult=等待承诺.all(CoveringCellQueriesPromises);
//在区域中创建一组用户
常量用户=[];
//遍历每个单元格和其中的每个用户,以查找范围内的用户
userQueriesResult.forEach(UserIncorveringCellQueryResult=>{
UserIncorveringCellQueryResult.forEach(userResult=>{
//从has创建单元格id
const user=userResult.data();
const s2CellId=new S2.s2CellId(user.geoHash.toString());
//验证用户是否在视图区域中
//因为单元格的区域将位于输入区域之外
if(s2RegionRect.contains(s2CellId.tolatng())){
user.id=userResult.id;
push(用户);
}
});
});
返回用户;
}

S2 geometry有很多方法可以找到覆盖单元(即,您要查找值的区域),因此,查看API并找到适合您的用例的匹配项是绝对值得的。

看看S2 geometry-。基本概念是将地球上的每个位置编码为64位,彼此靠近的位置是接近的。然后,您可以通过查找距离该位置+/-某个#的任何内容来查找x距离内的位置。现在,实际的实现有点复杂,因此您最终需要创建多个“单元”,即范围上的最小值和最大值。然后,查找每个单元格。(更多信息请访问。)

下面是在node.js/javascript中执行此操作的示例。我在后端使用它,让前端只通过区域/区域

    const S2 = require("node-s2");

    static async getUsersInRegion(region) {
    // create a region
    const s2RegionRect = new S2.S2LatLngRect(
      new S2.S2LatLng(region.NECorner.latitude, region.NECorner.longitude),
      new S2.S2LatLng(region.SWCorner.latitude, region.SWCorner.longitude),
    );

    // find the cell that will cover the requested region
    const coveringCells = S2.getCoverSync(s2RegionRect, { max_cells: 4 });

    // query all the users in each covering region/range simultaneously/in parallel
    const coveringCellQueriesPromies = coveringCells.map(coveringCell => {
      const cellMaxID = coveringCell
        .id()
        .rangeMax()
        .id();
      const cellMinID = coveringCell
        .id()
        .rangeMin()
        .id();

      return firestore
        .collection("User")
        .where("geoHash", "<=", cellMaxID)
        .where("geoHash", ">=", cellMinID).
        get();
    });

    // wait for all the queries to return
    const userQueriesResult = await Promise.all(coveringCellQueriesPromies);

    // create a set of users in the region
    const users = [];

    // iterate through each cell and each user in it to find those in the range
    userQueriesResult.forEach(userInCoveringCellQueryResult => {
      userInCoveringCellQueryResult.forEach(userResult => {
        // create a cell id from the has
        const user = userResult.data();
        const s2CellId = new S2.S2CellId(user.geoHash.toString());
        // validate that the user is in the view region
        // since cells will have areas outside of the input region
        if (s2RegionRect.contains(s2CellId.toLatLng())) {
          user.id = userResult.id;
          users.push(user);
        }
      });
    });

    return users;
  }
const S2=require(“节点-S2”);
静态异步getUsersInRegion(区域){
//创建一个区域
const s2RegionRect=新的S2.S2LatLngRect(
新的S2.S2LatLng(region.NECorner.lations,region.NECorner.lations),
新S2.S2LatLng(region.SWCorner.lation,region.SWCorner.longitude),
);
//查找将覆盖请求区域的单元格
const coveringCells=S2.getCoverSync(s2RegionRect,{max_cells:4});
//同时/并行查询每个覆盖区域/范围内的所有用户
const coveringCellQueriesPromies=coveringCells.map(coveringCell=>{
const cellMaxID=coveringCell
.id()
.rangeMax()
.id();
const cellMinID=覆盖单元
.id()
.rangeMin()
.id();
返回火库
.收集(“用户”)
.where(“geoHash”,“=”,cellMinID)。
get();
});
//等待所有查询返回
const userQueriesResult=等待承诺.all(CoveringCellQueriesPromises);
//在区域中创建一组用户
常量用户=[];
//遍历每个单元格和其中的每个用户,以查找范围内的用户
userQueriesResult.forEach(UserIncorveringCellQueryResult=>{
UserIncorveringCellQueryResult.forEach(userResult=>{
//从has创建单元格id
const user=userResult.data();
const s2CellId=new S2.s2CellId(user.geoHash.toString());
//验证用户是否在视图区域中
//因为单元格的区域将位于输入区域之外
if(s2RegionRect.contains(s2CellId.tolatng())){
user.id=userResult.id;
push(用户);
}
});
});
返回用户;
}

S2 geometry有很多方法可以找到覆盖单元(即,您要查找值的区域),因此绝对值得查看API并为您的用例找到合适的匹配项。

您熟悉吗?更多信息。你熟悉吗?更多信息请参见。这是一个实现s2的swift库这是一个实现s2的swift库