Following the example on the RevenDB site, I came up with this:
public class Place_ByLocationsAndCategoryId : AbstractIndexCreationTask<Place> {
public Place_ByLocationsAndCategoryId() {
Map = places => from p in places
select new { p.Categories, _ = Raven.Database.Indexing.SpatialIndex.Generate(p.Location.Lat, p.Location.Lng) };
}
}
Places look something like this:
Place {
string Id;
List<Category> Categories;
...
}
Categories look something like this:
Category {
string Id;
string Name;
...
}
How can I build my index so that I may query by places within a given radius of a lat/lng, and contains a given category?
I attempted to query the index above like so:
var placesFromDb = RavenSession.Advanced.LuceneQuery<Place>("Place/ByLocationsAndCategoryId").WhereIn("Id", new []{cat.Id}).WithinRadiusOf(radius: 5, latitude: Lat, longitude: Lng).ToList<Place>();
The query processes, but returns no results (when I know there are results to be returned. My error is probably in the .WhereIn()
statement, but when I tried to use .Where(x => x.Categories.Any(c => c.Id == id))
I got a build error stating it was obsolete.
I switched my index to this (as Ayende recommended)
public Place_ByLocationsAndCategoryId() {
Map = places => from p in places
select new { Categories_Id = p.Categories.Select(x => x.Id), _ = Raven.Database.Indexing.SpatialIndex.Generate(p.Location.Lat, p.Location.Lng) };
}
I create the index on the document store like so:
IndexCreation.CreateIndexes(typeof(Place_ByLocationsAndCategoryId).Assembly, Store);
I query it like so:
var placesFromDb = RavenSession.Advanced.LuceneQuery<Place>("Place/ByLocationsAndCategoryId").WhereEquals("Categories_Id ", cat.Id).WithinRadiusOf(radius: 15, latitude: Lat, longitude: Lng).ToList<Place>();
This is what the index looks like on RavenDB itself:
docs.Places
.Select(p => new {Categories_Id = p.Categories
.Select(x => x.Id), _ = SpatialIndex.Generate(((System.Double)(p.Location.Lat)), ((System.Double)(p.Location.Lng)))})
The query seems to run, but returns 0 results (I know there are places to be found). One thing I noticed is that the Lat and Lng data types in my model are floats, while it appears the index is set to Double.
Trying to cast the coordinates in the index like so, also does not work:
public Place_ByLocationsAndCategoryId() {
Map = places => from p in places
select new { Categories_Id = p.Categories.Select(x => x.Id), _ = Raven.Database.Indexing.SpatialIndex.Generate((float)p.Location.Lat, (float)p.Location.Lng) };
}
So I switched my model to use doubles; still returns 0 results.
If I remove the category part of the index, and query just the spatial part, it returns places. It appears the category part isn't functioning as planned.
In case it helps, here's how partially how a stored document looks (JSON view):
{
"Id": "4dca6d56d22da18f4e626f54",
"Name": "焼肉",
"Categories": [
{
"PlaceCategories": null,
"Name": "Korean Restaurant",
"Icon": "korean.png",
"Id": "4bf58dd8d48988d113941735",
"IsPrimary": true
}
],
"Location": {
"Lat": "35.6709824",
"Lng": "139.374588"
},
...
}
(note: Categories is the List, categories can have subcategories, in their own List property named PlaceCategories)
Here's the index error from the management studio:
Places/ByLocationsAndCategoryId Cannot convert type 'string' to 'float' 6/27/2012 places/1025 ... and repeats 50 times
I have already changed my model from float to double, because it looked like the spatial generator wanted doubles. Good chance that there are some errors in the log (can't see past 50), stating `Cannot convert type 'string' to 'float'
I'm curious, in my model previously, my Lat/Lng were floats. Where is the string coming from?
You want it like this:
Index:
public class Place_ByLocationsAndCategoryId : AbstractIndexCreationTask<Place> {
public Place_ByLocationsAndCategoryId() {
Map = places => from p in places
select new { Categories_Id = p.Categories.Select(x=>x.Id), _ = Raven.Database.Indexing.SpatialIndex.Generate(p.Location.Lat, p.Location.Lng) };
}
}
Query:
var placesFromDb = RavenSession.Advanced.LuceneQuery<Place>("Place/ByLocationsAndCategoryId").WhereEquals("Categories_Id ", cat.Id).WithinRadiusOf(radius: 5, latitude: Lat, longitude: Lng).ToList<Place>();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With