Reputation: 503
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
Reputation: 1805
Please, read MongoDB docs https://docs.mongodb.com/manual/geospatial-queries/
You need:
Store the location data like this:
location: { type: "Point", coordinates: [-73.846077, 40.828447] }
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
Reputation: 1
To use near by first create an index 2dsphere
like this:
db.places.createIndex( { location: "2dsphere" } )
Upvotes: 0
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
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