AppEngine / NDB如何对单个实体应用查询过滤器

时间:2014-04-29 18:11:28

标签: google-app-engine app-engine-ndb

在我们的应用程序中,我们经常有几个查询过滤器,用于检查存档状态,权限,实体层次结构等内容。这些过滤器是使用NDB的运算符重载构建的,例如: models.Item.isArchived == False。我相信这些也被称为FilterNode个实例。

给定一组这些FilterNode,如何将它们应用于在查询之外查找的单个实体?从Memcache说。

我的用例是我为端点设置了一组预定义的过滤器,该服务允许用户指定实体ID。我不是运行查询,而是通过ID获取。但我需要发布过滤器以确保它有效返回。

1 个答案:

答案 0 :(得分:2)

使用Query对象找到了几种使用内存过滤的方法(这两种方法都假定NDB ...但可以修改为非)

这第一个只使用Python内置“filter()”...它不处理可能在查询中的排序顺序:

def filter_entities(query, entities):
  #convert entities to list of protocol buffers
  entity_pbs = [ent._to_pb() for ent in entities if ent is not None]

  #assuming all entities are same type... just get type from first one
  model_klass = type(entities[0])

  #turn the query into a filter and hand it to builtin
  filtered = filter(query.filters._to_filter(), entity_pbs)

  #convert protocol buffers back into entities and hand back
  return [klass._from_pb(ent) for ent in filtered if ent is not None]

另一种方法使用datastore_query中的apply_query ... 考虑排序顺序:

from google.appengine.ext.ndb import tasklets
from google.appengine.datastore.datastore_query import apply_query

def apply_query(query, entities):
  #convert list of entities to list of protocol buffers
  entity_pbs = [ent._to_pb() for ent in entities if ent is not None]

  #convert NDB query to datastore_query (needs connection)
  conn = tasklets.get_context()._conn
  dsquery = query._get_query(conn)

  #call datastore_query.apply_query
  filtered = apply_query(dsquery, [entity_pbs])

  #convert protocol buffers back into entities and hand back
  return [klass._from_pb(ent) for ent in filtered if ent is not None]
显然,我正在访问一些可能在将来发生变化的隐藏方法......所以请确保你已经编写了测试来捕捉这种可能性