【问题标题】:How to make an elasticsearch query that filters on the maximum value of a field?如何进行过滤字段最大值的弹性搜索查询?
【发布时间】:2015-07-22 14:20:41
【问题描述】:

我希望能够查询文本,但也只检索数据中某个整数字段的最大值的结果。我已阅读有关聚合和过滤器的文档,但我不太明白我在寻找什么。

例如,我有一些被索引的重复数据除了整数字段外是相同的 - 我们称这个字段为lastseen

因此,作为一个例子,假设这些数据被放入 elasticsearch:

  //  these two the same except "lastseen" field
  curl -XPOST localhost:9200/myindex/myobject -d '{
    "field1": "dinner carrot potato broccoli",
    "field2": "something here",
    "lastseen": 1000
  }'

  curl -XPOST localhost:9200/myindex/myobject -d '{
    "field1": "dinner carrot potato broccoli",
    "field2": "something here",
    "somevalue": 100
  }'

  # and these two the same except "lastseen" field
  curl -XPOST localhost:9200/myindex/myobject -d '{
    "field1": "fish chicken something",
    "field2": "dinner",
    "lastseen": 2000
  }'

  curl -XPOST localhost:9200/myindex/myobject -d '{
    "field1": "fish chicken something",
    "field2": "dinner",
    "lastseen": 200
  }'

如果我查询"dinner"

  curl -XPOST localhost:9200/myindex -d '{  
   "query": {
        "query_string": {
            "query": "dinner"
        }
    }
    }'

我将返回 4 个结果。我想要一个过滤器,这样我只能得到两个结果 - 只有具有最大 lastseen 字段的项目。

显然不对,但希望它能让您了解我的目标:

{
    "query": {
        "query_string": {
            "query": "dinner"
        }
    },
    "filter": {
          "max": "lastseen"
        }

}

结果如下所示:

"hits": [
      {
        ...
        "_source": {
          "field1": "dinner carrot potato broccoli",
          "field2": "something here",
          "lastseen": 1000
        }
      },
      {
        ...
        "_source": {
          "field1": "fish chicken something",
          "field2": "dinner",
          "lastseen": 2000
        }
      } 
   ]

更新 1: 我尝试创建一个映射,将 lastseen 排除在索引之外。这没有用。仍然返回所有 4 个结果。

curl -XPOST localhost:9200/myindex -d '{  
    "mappings": {
      "myobject": {
        "properties": {
          "lastseen": {
            "type": "long",
            "store": "yes",
            "include_in_all": false
          }
        }
      }
    }
}'

更新 2: 我尝试使用 agg 方案 listed here, 进行重复数据删除,但没有成功,但更重要的是,我看不到将其与关键字搜索结合的方法。

【问题讨论】:

  • 如果您有两个带有lastseen: 2000 的文档,您希望同时返回,或者一个带有lastseen: 2000 和一个带有lastseen: 1000 的文档?
  • 另外,您认为什么是重复文件?我看到您将此类文档识别为具有相同 field1 的文档。
  • @AndreiStefan 重复的文档将具有相同的字段 1 和字段 2。
  • 然后你可以使用我在你的另一篇文章中描述的方法:stackoverflow.com/questions/31553928/…。使用_source 转换将两个字段连接到not_analyzed 第三个字段,并在我在答案中指定的聚合中使用它:"terms": { "field": "all_fields", "size": 2 }

标签: elasticsearch


【解决方案1】:

不理想,但我认为它可以满足您的需求。

更改field1 字段的映射,假设这是您用来定义“重复”文档的映射,如下所示:

PUT /lastseen
{
  "mappings": {
    "test": {
      "properties": {
        "field1": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "field2": {
          "type": "string"
        },
        "lastseen": {
          "type": "long"
        }
      }
    }
  }
}

意思是,您添加一个.raw 子字段,即not_analyzed,这意味着它将按原样索引,无需分析并拆分为术语。这是为了使有些“重复文件发现”成为可能。

然后,您需要在 field1.raw 上使用 terms 聚合(用于重复)和 top_hits 子聚合来为每个 field1 值获取单个文档:

GET /lastseen/test/_search
{
  "size": 0,
  "query": {
    "query_string": {
      "query": "dinner"
    }
  },
  "aggs": {
    "field1_unique": {
      "terms": {
        "field": "field1.raw",
        "size": 2
      },
      "aggs": {
        "first_one": {
          "top_hits": {
            "size": 1,
            "sort": [{"lastseen": {"order":"desc"}}]
          }
        }
      }
    }
  }
}

另外,top_hits 返回的单个文档是具有最高 lastseen 的文档("sort": [{"lastseen": {"order":"desc"}}] 使这成为可能)。

你将得到的结果是这些(在aggregations而不是hits下):

   ...
   "aggregations": {
      "field1_unique": {
         "doc_count_error_upper_bound": 0,
         "sum_other_doc_count": 0,
         "buckets": [
            {
               "key": "dinner carrot potato broccoli",
               "doc_count": 2,
               "first_one": {
                  "hits": {
                     "total": 2,
                     "max_score": null,
                     "hits": [
                        {
                           "_index": "lastseen",
                           "_type": "test",
                           "_id": "AU60ZObtjKWeJgeyudI-",
                           "_score": null,
                           "_source": {
                              "field1": "dinner carrot potato broccoli",
                              "field2": "something here",
                              "lastseen": 1000
                           },
                           "sort": [
                              1000
                           ]
                        }
                     ]
                  }
               }
            },
            {
               "key": "fish chicken something",
               "doc_count": 2,
               "first_one": {
                  "hits": {
                     "total": 2,
                     "max_score": null,
                     "hits": [
                        {
                           "_index": "lastseen",
                           "_type": "test",
                           "_id": "AU60ZObtjKWeJgeyudJA",
                           "_score": null,
                           "_source": {
                              "field1": "fish chicken something",
                              "field2": "dinner",
                              "lastseen": 2000
                           },
                           "sort": [
                              2000
                           ]
                        }
                     ]
                  }
               }
            }
         ]
      }
   }

【讨论】:

  • 谢谢。这正是我想要的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-29
  • 2015-01-25
  • 2016-04-03
  • 2017-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多