如何在app引擎中从多个实体中查找不同的标记集

时间:2012-06-30 12:11:14

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

我正在app引擎上编写一个系统来收集“样本”并提供查询和分析样本的服务。样本的数据模型与此类似:

class Sample(ndb.Model):
   category  = ndb.StringProperty()
   name      = ndb.StringProperty()
   data      = ndb.JsonProperty()
   timestamp = ndb.DateTimeProperty()
   tags      = ndb.StringProperty(repeated = True)

如您所见,每个样本都有一组字符串标记。例如:

['CustomerA', '2.0.5', 'featureX', 'logTypeB', ...]

我有一个处理程序,允许根据基本属性上的过滤器查询系统中的所有样本,并包括一组要求的标记。注意:结果集可能非常大,因此查询支持分页/限制,因此我一次返回一点数据。一切正常。

现在,当我在此基础上放置用户界面时,我想要一种向用户显示自动填充字段的方法,以输入其他标签以进一步过滤结果。因此,例如,如果他们将其限制为具有以下标记的样本:

Sample(..., tags=['CustomerA', '2.0.5', 'featureX'])
Sample(..., tags=['CustomerA', '2.0.5', 'featureY'])
Sample(..., tags=['CustomerB', '2.0.5', 'featureX'])
Sample(..., tags=['CustomerB', '2.0.5', 'featureX'])
Sample(..., tags=['CustomerB', '2.0.5', 'featureY'])

然后我想向他们展示一个包含以下内容的自动填充:

['CustomerA', 'CustomerB', '2.0.5', 'featureX', 'featureY']

换句话说,我需要一个处理程序,它可以返回当前结果集中存在的唯一标记列表。问题是我无论如何都无法在App Engine中看到这样做而不迭代所有结果样本(可能非常大)并构建一组唯一标记来返回。

我可以为系统中的所有标记保留一组单独的实体,但这也不能解决问题。它允许我快速找到系统中所有样本上存在的所有标记,但不能将其限制为通过当前过滤器的样本集。

关于我能以合理的方式实现这一目标的任何想法?

1 个答案:

答案 0 :(得分:1)

执行此操作的最佳方法是将标记保存在单独的实体中,该实体仅用于自动完成。由于标记名称是唯一的,因此您可以将标记用作实体键。使用ndb模型钩子可以使这变得简单。例如:

class SampleTag(ndb.Model):
  tag = ndb.StringProperty()

class Sample(ndb.Model):
  category  = ndb.StringProperty()
  name      = ndb.StringProperty()
  data      = ndb.JsonProperty()
  timestamp = ndb.DateTimeProperty()
  tags      = ndb.StringProperty(repeated = True)

  def _pre_put_hook(self):
    for tag in self.tags:
      SampleTag.get_or_insert(name=tag)

然后,您可以使用SampleTag中的值显示在自动填充中。

这只是一个例子 - 它效率不高,特别是如果你有很长的标签列表。要改进它,您应该确定自上次保存以来添加了哪些标记(如果有的话),并且只循环执行这些标记。此外,您可能希望使用异步调用,或者可以将_pre_put例程完全委托给任务队列,这将加快放置()模型所需的时间。

此外,这不会处理删除。这有点棘手,因为您无法事先知道标签是否存在于其他地方。为此,我将使用cron作业定期检查您的标签是否存在。