Search code examples
javamysqlgeolocationmybatisboundary

mysql query to filter by multiple coordinates boundaries


I have a database containing a list of cities with coordinates, and I am using mybatis with this query to find cities given a boundary.

SELECT * FROM cities 
WHERE lat > #{latMin} 
AND lat < #{latMax} 
AND lng > #{lngMin} 
AND lng < #{lngMax}

Now I have multiple boundaries and I call the query multiple times to have all the cities contained in all the boundaries, and things are getting slower.

To speed the things up, without changing my architecture, can I have a single query that takes in input a (maybe very long) list of boundaries? Maybe a stored procedure?

The contraints on this project are mybatis as persistence layer and mysql as db.

edit: this is my current mybatis method.

List<CityDTO> getCityNearPoint(@Param("latMin") Double latMin, @Param("latMax") Double latMax, 
             @Param("lngMin") Double lngMin, @Param("lngMax") Double lngMax);

I don't know how to pass an array of objects that contains the boundaries and map them to multiple ORs. Something like:

List<CityDTO> getCityNearBoundaries(BoundaryDTO[] boundaries);

Solution

  • Just combine multiple boundaries using OR. You can achive it using Dynamic SQL (s. foreach) or @SqlProvider annotated method, that will generate an appropriate SQL String. I would prefer to use Dynamic SQL. In xml it will look like this:

    <select id="selectCitiesByBoundaries" resultType="CityDTO">
      SELECT * FROM cities WHERE
      <foreach item="boundary" index="index" collection="#{boundaries}"
          open=" (" separator=") OR (" close=") ">
        lat > #{boundary.getLatMin()} AND
        lat < #{boundary.getLatMax()} AND
        lng > #{boundary.getLngMin()} AND
        lng < #{boundary.getLngMax()}
      </foreach>
    </select>