Thursday, January 31, 2013

Google AppEngine Search API

Introduction

In the article Geospatial Queries with Google App Engine I discussed my initial attempts to preform geospatial queries using +Google App Engine.  The described how I arrived at my solution but didn't provide any details on my implementation.

Datastore Entity vs Scored Document

I store all my data in Datastore entities, they are easy to save, fetch and run queries on.  So when I first started to read about the search API and having to create a document for indexing I felt there was a lot of overlay with entities.

I had to build a document with fields I had already saved in an entity, I initially created a document with only the fields I required for searching by location along with keys to my saved entities so I could fetch them.  Each time I added\updated an entity I called my index function to keep my index current with my entities.

IndexSpec indexSpec = IndexSpec.newBuilder().setName("locIndex").build();
Index idx = SearchServiceFactory.getSearchService().getIndex(indexSpec);

Locdoc = Document.newBuilder()                               
   .addField(Field.newBuilder().setName("id").setText(eid))                      
   .addField(Field.newBuilder().setName("parentid").setText(RegId))                           
   .addField(Field.newBuilder().setName("regid").setText(RegId))                            
   .addField(Field.newBuilder().setName("active").setText(Active))                                                      
   .addField(Field.newBuilder().setName("location").setGeoPoint(geoLoc))                
  .build();

idx.put(Locdoc);



Geospatial Index Search

After indexing my entities with the new search api, I used it to search for entities with a specific distance from a geopoint and it worked great. 

  String queryStr = "(active:1) AND 
   distance(location, geopoint(" + lat + ", " + lon + ")) < " + userad;

  Results<ScoredDocument> results = getLocIndex().search(queryStr);

        

Initially, I would get the entity key from the document and fetch the entity using the key.  However, I quickly realized this was a bad idea. I check my dashboard quotes and discovered I was hitting two quotes categories "Datastore Read Operations" and "Search API Calls".



Optimization to minimize quote impact

Since I had to use the Search API to locate data by location, I decided to examine all location based searches in my app and encode into the indexed document all the fields I required to handle a user response.

This resulted in much lower Datastore Read Operations and an increase in the response time.  Remember to limit the amount of data you push into your indexed document because there are limitations. See Search API quote.

Thanks for reading, follow me on G+ at +Tim O'Brien

+Kyght
www.kyght.com
tobrien@kyght.com




Note: The above icon is the property of Google and is only here to provide readers with
a visual recognition of the Google product.




No comments: