开发者社区 问答 正文

Solr中的完整外部连接

我正在尝试对两个集合进行完全外部联接。给出collection1的文档如下所示:

{
id: 234982032,
name: example,
listId: 123
}

并collection2带有如下所示的文档:

{
id: 123,
description: desc1
}

我期望这样的结果:

{
id: 234982032,
name: example,
description: desc1
}

我尝试使用此命令:

fq={!join from=listId to=id fromIndex=collection2}description:desc1

但这只会导致内部联接。有没有一种方法可以使用过滤器查询将两个集合进行外部联接?如果这不可能,是否有可以执行此操作的插件?

展开
收起
垚tutu 2019-12-12 09:28:43 583 分享 版权
阿里云 AI 助理回答

在Elasticsearch中,直接实现完全外部联接(即包含左表所有记录及右表匹配记录,若无匹配则显示NULL或默认值)并不像关系型数据库那样直观,因为Elasticsearch设计初衷是面向文档的搜索引擎,而非传统的关系型数据库。不过,你可以通过一些间接的方式来模拟这种行为。

一种常见的做法是使用bool查询结合should子句来尝试从两个集合中检索数据,并且对缺失的数据进行特殊处理。具体到你的场景,可以考虑以下步骤:

  1. 首先,从collection1中获取所有文档。
  2. 然后,对于每个来自collection1的文档,尝试查找collection2中与之匹配的文档。
  3. 如果找到匹配项,则合并信息;如果没有找到匹配项,手动插入期望的默认值(如description: "N/A")。

由于Elasticsearch查询本身不直接支持这种“左外联接”逻辑,你可能需要在应用层实现这个逻辑。一个简化的示例流程如下:

  • 发起一个查询以获取collection1的所有文档。
  • 对于每条结果,执行另一个查询去collection2中寻找匹配的description。这可以通过编写脚本或者在应用程序代码中循环处理并单独查询来完成。
  • 如果在collection2中找到了匹配项,就将信息合并;如果没有找到,就在结果集中为该字段添加默认值。

应用层解决方案示例

在实际操作中,你可能需要编写一段应用程序代码(比如使用Python和Elasticsearch客户端库),先查询collection1,然后针对每个结果,执行一个查询去查找collection2中的匹配项。如果找不到匹配,手动合成最终结果对象,填充默认值。

from elasticsearch import Elasticsearch

es = Elasticsearch()

# 查询collection1
collection1_docs = es.search(index="collection1", body={"query": {"match_all": {}}})

# 遍历collection1的结果
for doc in collection1_docs["hits"]["hits"]:
    # 尝试从collection2中根据listId查找匹配项
    res = es.get(index="collection2", id=doc["_source"]["listId"])
    if res["found"]:
        # 合并信息
        merged_doc = {**doc["_source"], **res["_source"]}
    else:
        # 没有找到匹配,手动添加默认值
        merged_doc = {**doc["_source"], "description": "N/A"}
    
    # 现在merged_doc包含了期望的格式,可进一步处理或存储

请注意,这种方法可能会导致大量的单独查询,性能上可能不如直接在数据库层面做联接高效,特别是在大数据量的情况下。因此,在选择这种方法时,请确保评估其对系统性能的影响,并考虑是否有必要优化查询逻辑或调整数据模型以适应Elasticsearch的特性。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答
问答地址: