Maryo
Maryo

Reputation: 503

Spring Data Mongodb Near Query not works

I would like to find the nearest shop. So I wrote this code:

public class ShopRepositoryImpl extends GenericRepositoryImpl<ShopEntity, String> implements ShopRepositoryCustom {

    @Autowired
    protected MongoTemplate template;

    @Override
    public GeoResult<ShopEntity> findNearest(Point location) {
        List<GeoResult<ShopEntity>> result = template.geoNear(
                NearQuery.near(location).maxDistance(new Distance(70, Metrics.KILOMETERS))
                        .query(new Query(Criteria.where("location")).limit(1)),
                ShopEntity.class).getContent();
        if (result.isEmpty())  {
            return null;
        } else {
            return result.get(0);
        }
    }
}

In tomcat console there is :

2016-01-17 12:13:26.151  WARN 645 --- [nio-8080-exec-2]     o.s.data.mongodb.core.MongoTemplate      : Command execution of 
{ "geoNear" : "shop" , "query" : { "location" : { }} , "maxDistance" : 0.010974991600211786 , "distanceMultiplier" : 6378.137 , "num" : 1 , "near" : [ 48.8703939 , 2.0] , "spherical" : true} 
failed: no geo indices for geoNear

And I tried this :

public interface ShopRepository extends GenericRepository<ShopEntity, String>, ShopRepositoryCustom {
    GeoResults<ShopEntity> findByLocationNear(Point location, Distance distance);
}

No result

In my database I have one element :

  {
    "name": "A shop",
    "street": "149 Rue Montmartre",
    "city": "Paris",
    "zip": "75002",
    "country": "France",
    "location": {
      "x": 48.8703937,
      "y": 2.3422999
    }
  }

Upvotes: 2

Views: 4493

Answers (4)

Caio Santos
Caio Santos

Reputation: 1805

Please, read MongoDB docs https://docs.mongodb.com/manual/geospatial-queries/

You need:

  1. Store the location data like this:

    location: { type: "Point", coordinates: [-73.846077, 40.828447] }

  2. Create a geo index

    db.collection.createIndex( { location : "2dsphere" } )

You can make SpringData work for you, using this in your entity:

@GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)
private MongodbLocation location;

And enabling index creation in the properties file:

data.mongodb.auto-index-creation: true

An example of POJO for the location object:

public class MongodbLocation {
    List<Double> coordinates;
    String type;
}

And don't forget: Point object and coordinates list need longitude first, then latitude.

Then... you can use something like this:

public interface AdRepository extends MongoRepository<AdEntity, String> {
    GeoResults<AdEntity> findByAddressLocationNear(Point p, Distance d);

    GeoPage<AdEntity> findByAddressLocationNear(Point p, Distance d, Pageable pageable);
}

Upvotes: 0

Maryan Basarab
Maryan Basarab

Reputation: 1

To use near by first create an index 2dsphere like this:

db.places.createIndex( { location: "2dsphere" } )

Upvotes: 0

Abdessamad ABOUKDIR
Abdessamad ABOUKDIR

Reputation: 141

You can just use the simple @Query annotation. Index your location attribute by running in your mongod command line : db.yourCollection.createIndex( { location : "2dsphere" } ). Then use the query annotation in your MongoRepository :

    @Repository
public interface ShopRepository extends MongoRepository<Shop, String>{

    @Query(value = "{\"location\":\n" +
"       { $near :\n" +
"          {\n" +
"            $geometry : {\n" +
"               type : \"Point\" ,\n" +
"               coordinates : [ ?0, ?1] }\n" +
"          }\n" +
"       }}")
    public List<Shop> nearByShops(double longitude, double latitude);

}

Upvotes: 1

jonrsharpe
jonrsharpe

Reputation: 122154

I had some problems with a near query recently, which I solved as follows:

mongoTemplate.indexOps(MyClass.class).ensureIndex(new GeospatialIndex("attribute.holding.coordinates"));
NearQuery nearQuery = NearQuery.near(x, y);
final GeoResults<MyClass> geoResults = mongoTemplate.geoNear(nearQuery, MyClass.class);
return geoResults.getContent().stream().map(GeoResult::getContent).collect(Collectors.toList());

This explicitly applies a geospatial index, then uses it to lookup nearby objects.

Upvotes: 0

Related Questions