【问题标题】:Elasticsearch Pipelined search?Elasticsearch 管道搜索?
【发布时间】:2020-02-06 12:16:59
【问题描述】:

我在公司使用 Elasticsearch 已经有一段时间了,到目前为止,我们的搜索似乎效果很好。 我们从客户那里看到了更复杂的用例,需要更多的“临时/高级”查询功能和文档间关系(或传统意义上的联接)。 我知道 ES 不是为连接而构建的,非规范化是推荐的方式。到目前为止,我们一直在对文档进行非规范化以支持每个用例,而这本身对我们来说变得过于复杂和昂贵,因为我们的客户必须等待很长时间才能推出此代码更改。

我们的业务经常批评我们“嘿,您的数据模型不正确。它不适合更智能的查询”。团队每次都很难让他们理解为什么需要非规范化。

几个问题的例子:

"Find me all the persons having the same birthdays"
"Find me all the persons travelling to the same cities within the same time frame"

想象每个事件文档都是带有旅行详细信息的人员记录。

那么有没有管道搜索的概念,我可以将搜索分成多个搜索查询并将一个的输出作为输入传递给另一个? 或者有没有其他推荐的方法来解决这些类型的问题,而不必让海洋沸腾?

【问题讨论】:

  • 您能分享一份“带有旅行详细信息的人员记录”的样本文件吗?很确定上述两个查询可以通过聚合简单地解决。
  • 只是出于好奇,您为什么为此选择 nosql 方法?似乎关系数据库可以做的很好

标签: elasticsearch elasticsearch-aggregation elasticsearch-6


【解决方案1】:

上面的两个查询可以通过聚合来解决。

我假设以下示例文档/模式:

{
  "firstName": "John",
  "lastName": "Doe",
  "birthDate": "1998-04-02",
  "travelDate": "2019-10-31",
  "city": "London"
}

第一个通过在生日字段(一年中的某天)和 min_doc_count: 2 上聚合 terms,例如:

{
  "size": 0,
  "aggs": {
    "birthdays": {
      "terms": {
        "script": "return LocalDate.parse(params._source.birthDate).format(DateTimeFormatter.ofPattern('MM/dd'))",
        "min_doc_count": 2
      },
      "aggs": {
        "persons": {
          "top_hits": {}
        }
      }
    }
  }
}

第二个是在city 字段上使用terms 聚合进行聚合,并在所需时间范围内使用travelDate 字段上的range 查询进行约束:

{
  "size": 0,
  "query": {
    "range": {
      "travelDate": {
        "gte": "2019-10-01",
        "lt": "2019-11-01"
      }
    }
  },
  "aggs": {
    "cities": {
      "terms": {
        "field": "city.keyword"
      },
      "aggs": {
        "persons": {
          "top_hits": {}
        }
      }
    }
  }
}

第二个查询也可以用field collapsing:

{
  "_source": false,
  "query": {
    "range": {
      "travelDate": {
        "gte": "2019-10-01",
        "lt": "2019-11-01"
      }
    }
  },
  "collapse": {
    "field": "city.keyword",
    "inner_hits": {
      "name": "people"
    }
  }
}

如果您同时需要两个聚合,那么绝对可以这样做:

{
  "size": 0,
  "aggs": {
    "birthdays": {
      "terms": {
        "script": "return LocalDate.parse(params._source.birthDate).format(DateTimeFormatter.ofPattern('MM/dd'))",
        "min_doc_count": 2
      },
      "aggs": {
        "persons": {
          "top_hits": {}
        }
      }
    },
    "travels": {
      "filter": {
        "range": {
          "travelDate": {
            "gte": "2019-10-01",
            "lt": "2019-11-01"
          }
        }
      },
      "aggs": {
        "cities": {
          "terms": {
            "field": "city.keyword"
          },
          "aggs": {
            "persons": {
              "top_hits": {}
            }
          }
        }
      }
    }
  }
}

【讨论】:

  • 我可以“和”这两种完全不同的聚合吗?我是否必须考虑将术语聚合嵌套在彼此或复合聚合中?
  • 太棒了,很高兴它有帮助!
猜你喜欢
  • 1970-01-01
  • 2019-04-21
  • 2016-08-29
  • 2019-04-07
  • 1970-01-01
  • 2022-08-17
  • 2022-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多