我正在尝试设计一个与 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 对象实际上包含这些字段的值。