【问题标题】:Join query in ElasticSearch在 ElasticSearch 中加入查询
【发布时间】:2014-03-24 13:38:19
【问题描述】:

有什么方法(查询)可以在 ElasticSearch 中加入下面的 2 个 JSON

{
product_id: "1111",
price: "23.56",
stock: "100"
}

{
product_id: "1111",
category: "iPhone case",
manufacturer: "Belkin"
}

在 Logstash 中以 2 种不同类型处理(输入)以上 2 个 JSON,因此它们的索引在 Elasticsearch 中的不同“类型”字段中可用。

我想要的是在 product_id 字段上加入 2 个 JSON。

【问题讨论】:

  • 有人可以回复我吗?

标签: elasticsearch logstash kibana


【解决方案1】:

这取决于您说 JOIN 时的意图。 Elasticsearch 不像常规数据库那样支持表之间的 JOIN。它是一个文本搜索引擎,用于管理索引中的文档。

另一方面,您可以使用每种类型共有的字段在同一索引中搜索多种类型。

例如获取您的数据,我可以创建具有 2 种类型的索引,它们的数据如下:

curl -XPOST localhost:9200/product -d '{
    "settings" : {
        "number_of_shards" : 5
    }
}'

curl -XPOST localhost:9200/product/type1/_mapping -d '{
        "type1" : {
            "properties" : {
                "product_id" : { "type" : "string" },
                "price" : { "type" : "integer" },
                "stock" : { "type" : "integer" }
            }
        }   
}'              

curl -XPOST localhost:9200/product/type2/_mapping -d '{
        "type2" : {
            "properties" : {
                "product_id" : { "type" : "string" },
                "category" : { "type" : "string" },
                "manufacturer" : { "type" : "string" }
            }
        }
}'  

curl -XPOST localhost:9200/product/type1/1 -d '{
        product_id: "1111", 
        price: "23",
        stock: "100"
}'

curl -XPOST localhost:9200/product/type2/1 -d '{
        product_id: "1111",
        category: "iPhone case",
        manufacturer: "Belkin"
}'

我有效地创建了一个名为 product 的索引,其中包含 2 个类型 type1 和 type2。 现在我可以执行以下查询,它将返回两个文档:

curl -XGET 'http://localhost:9200/product/_search?pretty=1' -d '{
    "query": {
        "query_string" : {
            "query" : "product_id:1111"
        }
    }
}'

{
  "took" : 95,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.5945348,
    "hits" : [ {
      "_index" : "product",
      "_type" : "type1",
      "_id" : "1",
      "_score" : 0.5945348, "_source" : {
    product_id: "1111",
    price: "23",
    stock: "100"
}
    }, {
      "_index" : "product",
      "_type" : "type2",
      "_id" : "1",
      "_score" : 0.5945348, "_source" : {
    product_id: "1111",
    category: "iPhone case",
    manufacturer: "Belkin"
}
    } ]
  }
}

原因是因为 Elasticsearch 将搜索该索引中的所有文档,而不管它们的类型如何。这仍然与 JOIN 不同,因为 Elasticsearch 不会对属于每种类型的文档进行笛卡尔积。

希望有帮助

【讨论】:

  • 非常感谢您的回复,您能否告诉我在这种情况下最好的/替代解决方案是什么。正如你上面提到的,我确实有一个索引“产品”和两种类型“type1”和“type2”,两种类型都有一个公共字段“product_id”。现在,对于我来说,将 JSON 合并并在新索引中编入索引或在 Elasticsearch 中键入相同的“product_id”的可能选项是什么。仅供参考,我正在使用 ELK 堆栈(Elasticsearch、Logstash 和 Kibana)。
  • 我不确定我是否理解您想要实现的目标,您的最终目标是什么?最后你想在 Kibana 中显示什么?
  • 您的回答肯定很有用。实际上@isaac.hazan 我的最终目标是在 Kibana 的单个事件下显示 'product_id'、'price'、'stock'、'category' 和 'manufacturer'。
  • 要支持你的答案,我需要 15 名声望,但我在 Stake Overflow 中只有三天大 :(
  • 关于您的最终目标,我认为这不可能作为内置功能。我在另一个项目中处理了相同类型的问题,我克服的方法是在顶部开发一个接受 2 个事件的层,合并它们并将它们作为单个事件保存到 elasticsearch 中。话虽如此,请记住,在 Kibana 中,如果您只查询不带类型的索引,您将获得整个数据集,这在技术上意味着您将能够显示一些控制,但我同意这对于直方图来说并不理想,例如您将举办 2 个活动而不是 1 个。
【解决方案2】:

isaac.hazan 的回答效果很好,但我想补充几点帮助我解决这种情况:

当我试图解决一个类似问题时,我登陆了这个页面,因为我必须根据另一个索引的文档排除一个索引的多个记录。缺乏关系是非结构化数据库的主要缺点之一。

Handling Relationships 上的 elasticsearch 文档页面解释了很多。

四种常用技术用于管理 Elasticsearch 中的关系数据:

  • 应用程序端联接
  • 数据非规范化
  • 嵌套对象
  • 父/子关系

通常最终的解决方案需要混合使用这些技术。

我主要使用嵌套对象和应用程序端连接。虽然使用相同的字段名称可以暂时解决问题,但我认为最好重新考虑并为您的应用程序创建最适合的映射。

例如,您可能想列出价格大于 x 的所有产品,或者列出所有不再有库存的产品。要处理这种情况,如果您使用上述解决方案之一会有所帮助。

【讨论】:

    【解决方案3】:

    要在 Elasticsearch 上执行连接,请查看 Siren“Federate”插件。它通过扩展 Elasticsearch 原生查询语法来添加连接功能。

    https://siren.io/federate/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-06
      • 1970-01-01
      • 1970-01-01
      • 2013-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多