在GAE上缓存查询结果

时间:2015-08-07 11:45:45

标签: python google-app-engine memcached google-cloud-datastore

我在3个月前开始使用Google App Engine,我对memcaching上的Python有疑问。 我试着尽可能地描述我的问题。

我使用ndb (App Engine Datastore)并且我有一个"表"像这样的实体:

class Event(ndb.Model):
    dateInsert = ndb.DateTimeProperty(auto_now_add=True)              # Inserting date
    notes = ndb.StringProperty(indexed=False)                         # event notes
    geohash = ndb.StringProperty(required=True)                       # Coordinates geohash 
    eventLatitude = ndb.FloatProperty(indexed=True, required=True)    # self explanatory
    eventLongitude = ndb.FloatProperty(indexed=True, required=True)   # self explanatory

客户端(例如,使用移动应用程序)用户可以在数据存储区中存储指定坐标中的事件。 那些插入的事件当然可以通过移动应用程序(在地图上)和网站上看到。 现在要检索存储的事件,客户端调用一个web方法来搜索给定位置附近的事件:

class getEvents(webapp.RequestHandler):
    def get(self):
        #blablabla get passed parameters
        #[...]

        # hMinPos and hMaxPos are hashed coordinates passed by client + X meters. 
        # In this way I can filter stored events in a precise bounding box.
        # For example, I can get events near my location in a box of 5000 meters
        qryEvent = Event.query(ndb.AND(Event.geohash >= hMinPos, Event.geohash <= hMaxPos))
        events = qryEvent.fetch(1000)

然后我必须以循环周期获取每个结果以创建一个JSON来存储在列表中并将其返回给客户端。 所以它是

for event in events:
    #do my stuff

一切都运行正常,但是大问题是无用的读取操作每次我称之为该方法。 我的意思是,每次调用方法时,它都会获取与其他客户端请求相同的事件,或者比同一客户端的先前请求更糟,相同的事件(如果我移动50米并且我发出客户端请求,事件与之前的请求相同ad 99% )。 这将很快占用配额和读取操作超额配额。 我想我应该使用memcache来存储已获取的事件,并在从数据存储区读取之前在memcache中读取它们,但我不知道用我的结构来实现它。

我的想法是使用geohash作为memcache密钥,但是我不能遍历缓存的元素,我只能对给定的密钥进行精确获取,因此我的解决方案不适用(我无法解决)使用密钥直接访问memcache,我需要在memcache元素中迭代以找到适合我的坐标范围请求的事件。 有人有提示或建议吗?

1 个答案:

答案 0 :(得分:1)

我可以想到2个解决方案:

1)在memcached中存储具有纬度 - 经度标识符的较小框(例如100米长)的信息。您可以从ndb请求一个大的例如5500米长,并保存memcached中所有包含的小方框的信息。当用户移动50米,100米或400米时,您将能够使用memcached数据向她提供答案,如果有人靠近该地点(500米内),则会发生同样的事情。

2)您可以使用ElasticSearch,特别是Geo Distance Filter。有了它,您可以过滤"documents that include only hits that exists within a specific distance from a geo point"

注意:如果 getEvents 在5000米的方框中返回事件,那么移动50米但距离较远时,您不应该触发新请求。