1

我正在尝试设计一个与 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 仅存在于 groupId 为 X1 的 Foo )
  • 每个用户只能访问具有特定组 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 进行了超过 1 次查询
  • 更重要的缺点是似乎没有一种简单的方法可以组合每个单独查询的结果。如果每个查询都返回结果,则每个返回文档的分数都会归一化为该查询中的所有结果,那么您将如何组合来自不同查询的结果?

似乎解决方案 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。请注意,文档的字段根据它们所拥有的 groupId 是不同的。我们系统中的单个用户可以访问两个进程中所有人员的所有信息。

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

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

* --更新 2--

我们会超过 1000 个字段限制的原因是因为 Foo 对象的模式是用户可配置的。例如,用户可以创建一个名为“销售流程”的 groupId,并添加一些用户定义的字段,如“潜在客户来源”、“感兴趣的产品”、“结束日期”等。

因为每个用户都可以自定义他们的组,跨越数百万用户,所有字段的超集肯定>1000。上面列出的示例 Foo 对象有点简单。groupId 实际上是一个指向用户创建的他们想要的所有自定义字段的模式的 Id。foo 对象实际上包含这些字段的值。

4

1 回答 1

2

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

对我来说,基于用户输入动态定义模式(即字段名称集)的概念是一个危险信号。我可能不愿意做出笼统的声明,即永远不应该做这样的事情。但这似乎确实值得重新考虑。

如果这些字段是用户定义的,那么似乎没有系统可以对它们产生影响的特定处理知识。换言之,对于系统而言,字段必须只是通用信息容器。你会同意吗?

所以,我的想法会朝着消除它的这一方面的方向发展,以一种或另一种方式。

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

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

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

于 2013-10-30T23:25:42.083 回答