如何为共享文档设计Appengine Search API索引?

时间:2013-10-16 22:28:30

标签: java google-app-engine search

我正在尝试设计一个与AppEngine Search API(java)一起使用的好架构,并且在下列用例的情况下会喜欢一些意见:

在我们的应用程序中,我们希望用户能够搜索Foo类型的对象。 Foo对象看起来像:

{
    groupId: "x1",
    name: "somename"
    someFieldA: "somevalue",
    someFieldB: "somevalue",
    someFieldC: "somevalue"
}

但是,不同的Foo对象可能如下所示:

{
    groupId: "x2",
    name: "somename"
    someFieldD: "somevalue",
    someFieldE: "somevalue",
    someFieldF: "somevalue"
}

群组ID非常重要:

  • groupId字段确定每个Foo对象具有的属性 (即someFieldA,someFieldB,someFieldC仅存在于Foo的a X1的groupId
  • 每个用户只能访问具有特定组ID的Foo

因此,我想要解决的用例是,用户应该能够搜索Foo(通过其任何字段),因为他们只能访问某些Foo。以下是两个都有缺点的解决方案:

解决方案1:

  • 为所有Foo创建1个索引。
  • 此索引的字段是每个Foo中每个字段的SUPERSET。
  • 这很有效,因为用户搜索可以翻译为:userquery AND (groupId:X OR groupId:Y OR groupId:Z)
  • 它也很好,因为所有Foo都不管或者他们的groupId是相对于彼此进行排序和排序的。
  • 我不认为方法有效,因为每个模式都有1000个字段限制,并且可能有足够的groupid使得所有Foo的所有字段的超集更多超过1000个字段

解决方案2:

  • 为groupId创建1个索引
  • 用户搜索会转换为异步搜索(用户有权访问每个groupid 1个),然后必须合并结果
  • 这样做的好处是我们不会遇到1000字段限制
  • 一个缺点是,当您对搜索API进行多次查询时,这可能会花费更多。
  • 更重要的缺点是似乎没有一种简单的方法来组合每个单独查询的结果。如果每个查询都返回结果,则每个返回文档的分数将标准化为该查询中的所有结果,那么您将如何组合来自不同查询的结果?

似乎解决方案2是最理想的 - 但我无法弄清楚如何解决结果问题的组合/排名。

有什么想法吗?

- 更新1 -

以下是文档内容的更具体的示例:

{
    groupId:"Hiring Process",
    name: "Bob Smith",
    position: "Software Engineer",
    yearsOfExperience: 6
}

{
    groupId:"Sales Process",
    name: "Frank J",
    company: "Engineering Engineer Inc.",
    contactInfo: "555-555-5555"
}

{
    groupId:"Hiring Process",
    name: "Jane Doe",
    position: "Marketing",
    yearsOfExperience: 3
}

{
    groupId:"Sales Process",
    name: "Jane Moe",
    company: "Google",
    contactInfo: "666-666-6666"
}

如上所示,这些文件代表了人们。每个对象的组ID为“Sales Process”或“Hiring Process”。请注意,文档的字段根据它们具有的groupId而不同。我们系统中的单个用户可以访问有关这两个进程中所有人的所有信息。

因此,假设我们的用户搜索engineer,应该返回2个结果,1个用于Bob Smith,1个用于Frank J。但是,Frank J结果应该排名/得分更高,因为“工程师”一词在文档中出现两次。

因为所有文档的字段数量的超集可能具有> 1000的大小,所以我认为我不能将所有文档放在1个索引中。如果我对索引进行分片(每组ID为1),我如何在多组搜索结果中排名/得分?

* - 更新2 -

我们超过1000字段限制的原因是因为Foo对象的模式是用户可配置的。例如,用户可以创建一个名为“Sales Process”的groupId,并添加一些用户定义的字段,如“lead source”,“product interest”,“close date”等。

由于每个用户都可以在数百万用户中自定义他们的群组,因此所有字段的超集肯定都是> 1000。上面列出的示例Foo对象有点简单。 groupId实际上是一个Id,指向用户创建的所有自定义字段的架构。 foo对象实际上包含这些字段的值。

1 个答案:

答案 0 :(得分:2)

这是一个半生不熟的“答案”。我的希望是,它可以激发你的思考,足以让你想出一个能够运作良好的真实答案。

对我来说,基于用户输入动态定义模式(即字段名称集)的概念是一个红色标记。我可能不愿意做一个全面的声明,即一个人应该从不做这样的事情。但它似乎值得再次考虑。

如果字段是用户定义的,那么似乎可能没有系统可以对它们施加的特定处理知识。换句话说,对于系统,字段必须只是通用信息容器。你同意吗?

所以,我的想法会朝着消除这方面的方向发展,无论如何。

我想知道是否有一种方法可以使实际字段名称通用(例如,UserField1,UserField2等),并将用户提供的字段名称的per-groupId映射存储到实际字段名称。似乎这对于全局搜索(搜索查询没有提到字段名称)可以正常工作。

我确实认识到用户不能简单地编写像[engineer yearsOfExperience> 3]这样的查询。但是,想一想,他们还能这样做吗?您是否允许他们定义用户定义字段的类型?

无论如何,我的意思是这些“领域”被不恰当地考虑在内。不知何故,用户定义的字段名称希望存储为数据,而不是用作动态模式。