2

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

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 中执行此操作。

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

关于我可以做些什么来以合理的方式实现这一点的任何想法?

4

1 回答 1

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 例程完全委托给任务队列,这将加快 put() 模型所需的时间。

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

于 2012-06-30T21:36:03.703 回答