Как найти многоугольники, содержащие заданную точку в Elasticsearch

Мне нужно создать запрос к базе данных с примерно 50 тысячами полигонов местности (хранящимися как полигоны geo_shape на ES), где я даю точку, и он возвращает каждый многоугольник, содержащий эту точку.

Мне удалось сделать это с помощью перколятных запросов (пример ниже), но я где-то читал, что перколитные запросы плохо масштабируются.

Есть ли более эффективный способ добиться такого поведения?

Пример использования перколата:

Демо-полигоны

PUT geo_demo
{
  "mappings": {
    "properties": {
      "thepoly": {
        "type": "percolator"
      },
      "thepoint": {
        "type": "geo_point"
      }
    }
  }
}

#region 1 (red)
POST /geo_demo/_doc/1
{
  "thepoly": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_polygon": {
          "thepoint": {
            "points": [
              "-23.573978,-46.664806",
              "-23.583978,-46.664806",
              "-23.583978,-46.658806",
              "-23.573978,-46.658806",
              "-23.573978,-46.664806"
            ]
          }
        }
      }
    }
  }
}

#region 2 (green)
POST /geo_demo/_doc/2
{
  "thepoly": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_polygon": {
          "thepoint": {
            "points": [
              "-23.579978,-46.664806",
              "-23.583978,-46.664806",
              "-23.583978,-46.652806",
              "-23.579978,-46.652806",
              "-23.579978,-46.664806"
            ]
          }
        }
      }
    }
  }
}

#should match doc/1 only
GET /geo_demo/_search
{
  "query": {
    "percolate": {
      "field": "thepoly",
      "document": {
        "thepoint": "-23.577007,-46.661811"
      }
    }
  }
}

#should match both doc/1 and doc/2
GET /geo_demo/_search
{
  "query": {
    "percolate": {
      "field": "thepoly",
      "document": {
        "thepoint": "-23.582002,-46.661811"
      }
    }
  }
}

#should match doc/2 only
GET /geo_demo/_search
{
  "query": {
    "percolate": {
      "field": "thepoly",
      "document": {
        "thepoint": "-23.582041,-46.655717"
      }
    }
  }
}

#should match none
GET /geo_demo/_search
{
  "query": {
    "percolate": {
      "field": "thepoly",
      "document": {
        "thepoint": "-23.576771,-46.655674"
      }
    }
  }
}

1 ответ

Вам почти не нужен для этого elasticearch, если у вас нет веской причины.

Для полигонов 50K вы можете легко хранить их в куче или разложить каждый полигон на список геохешей.

у вас может быть карта в куче с геохешем в качестве ключа и идентификатором полигона в качестве значения.

когда у вас есть точка входа, вы сначала вычисляете геохеш, а затем используете Map#get чтобы проверить, находится ли точка на карте или какие многоугольники содержат эту точку.

Другие вопросы по тегам