Home > Software engineering >  Order documents by multiple geolocations
Order documents by multiple geolocations

Time:12-20

I am new to ElasticSearch and I try to create an index for companies that come with multiple branches in the city.

Each of the branches, it has its own geolocation point.

My companies document looks like this:

{
    "company_name": "Company X",
    "branch": [
        {
            "address": {
                // ... other fields
                "location": "0.0000,1.1111"
            }
        }
    ]
}

The index have the following mapping:

{
  "companies": {
    "mappings": {
      "dynamic_templates": [
        {
          "ids": {
            "match": "id",
            "match_mapping_type": "long",
            "mapping": {
              "type": "long"
            }
          }
        },
        {
          "company_locations": {
            "match": "location",
            "match_mapping_type": "string",
            "mapping": {
              "type": "geo_point"
            }
          }
        }
      ],
      "properties": {
        "branch": {
          "properties": {
            "address": {
              "properties": {
                // ...
                "location": {
                  "type": "geo_point"
                },
                // ...
              }
            },
          }
        }
      }
    }
  }
}

Now, in the ElasticSearch I've indexed the following documents:

{
    "company_name": "Company #1",
    "branch": [
        {
            "address": {
                "location": "39.615,19.8948"
            }
        }
    ]
}

and

{
    "company_name": "Company #2",
    "branch": [
        {
            "address": {
                "location": "39.586,19.9028"
            }
        },
        {
            "address": {
                "location": "39.612,19.9134"
            }
        },
        {
            "address": {
                "location": "39.607,19.8946"
            }
        }
    ]
}

Now what is my problem. If I try to run the following search query, unfortunately the company displayed first is the Company #2 although the geodistance query has the location data of the Company #1:

GET companies/_search
{
  
  "fields": [
    "company_name", 
    "branch.address.location"
  ],
  "_source": false,
  "sort": [
    {
      "_geo_distance": {
        "branch.address.location": {
          "lon": 39.615,
          "lat": 19.8948
        },
        "order": "asc",
        "unit": "km"
      }
    }
  ]
}

Am I doing something wrong? Is there a way to sort the search results using this method?

Please keep in mind that if for example search with a geolocation that is more close to some geolocations of the "Comapny #2", in this case I need the Company #2 to be first.

Finally, if the setup I have isn't correct for what I require, if there's any other way to achieve that same result with different document structure, please let me know. I am still in the beginning of the project, and It's simple to adapt to what is more appropriate.

CodePudding user response:

The documentation here says "Geopoint expressed as a string with the format: "lat,lon"." Your location is "location": "39.615,19.8948", maybe the query must be below:

 "branch.address.location": {
     "lat": 39.615,
     "lon": 19.8948
  }

My Tests:

PUT idx_test
{
  "mappings": {
    "properties": {
      "branch": {
        "properties": {
          "address": {
            "properties": {
              "location": {
                "type": "geo_point"
              }
            }
          }
        }
      }
    }
  }
}

POST idx_test/_doc/1
{
  "company_name": "Company #1",
  "branch": [
    {
      "address": {
        "location": "39.615,19.8948"
      }
    }
    ]
}

POST idx_test/_doc/2
{
    "company_name": "Company #2",
    "branch": [
        {
            "address": {
                "location": "39.586,19.9028"
            }
        },
        {
            "address": {
                "location": "39.612,19.9134"
            }
        },
        {
            "address": {
                "location": "39.607,19.8946"
            }
        }
    ]
}

Search by location "39.607,19.8946" company #2

GET idx_test/_search?
{
  "fields": [
    "company_name",
    "branch.address.location"
  ],
  "_source": false,
  "sort": [
    {
      "_geo_distance": {
        "branch.address.location": {
          "lat": 39.607,
          "lon": 19.8946
        },
        "order": "asc", 
        "unit": "km"
      }
    }
  ]
}

Response:

"hits": [
  {
    "_index": "idx_test",
    "_id": "2",
    "_score": null,
    "fields": {
      "branch.address.location": [
        {
          "coordinates": [
            19.9028,
            39.586
          ],
          "type": "Point"
        },
        {
          "coordinates": [
            19.9134,
            39.612
          ],
          "type": "Point"
        },
        {
          "coordinates": [
            19.8946,
            39.607
          ],
          "type": "Point"
        }
      ],
      "company_name": [
        "Company #2"
      ]
    },
    "sort": [
      0
    ]
  },
  {
    "_index": "idx_test",
    "_id": "1",
    "_score": null,
    "fields": {
      "branch.address.location": [
        {
          "coordinates": [
            19.8948,
            39.615
          ],
          "type": "Point"
        }
      ],
      "company_name": [
        "Company #1"
      ]
    },
    "sort": [
      0.8897252783915647
    ]
  }
]

Search by location "39.615,19.8948" company #1

GET idx_test/_search?
{
  "fields": [
    "company_name",
    "branch.address.location"
  ],
  "_source": false,
  "sort": [
    {
      "_geo_distance": {
        "branch.address.location": {
          "lat": 39.615,
          "lon": 19.8948
        },
        "order": "asc", 
        "unit": "km"
      }
    }
  ]
}

Response

"hits": [
  {
    "_index": "idx_test",
    "_id": "1",
    "_score": null,
    "fields": {
      "branch.address.location": [
        {
          "coordinates": [
            19.8948,
            39.615
          ],
          "type": "Point"
        }
      ],
      "company_name": [
        "Company #1"
      ]
    },
    "sort": [
      0
    ]
  },
  {
    "_index": "idx_test",
    "_id": "2",
    "_score": null,
    "fields": {
      "branch.address.location": [
        {
          "coordinates": [
            19.9028,
            39.586
          ],
          "type": "Point"
        },
        {
          "coordinates": [
            19.9134,
            39.612
          ],
          "type": "Point"
        },
        {
          "coordinates": [
            19.8946,
            39.607
          ],
          "type": "Point"
        }
      ],
      "company_name": [
        "Company #2"
      ]
    },
    "sort": [
      0.8897285575578558
    ]
  }
]
  • Related