当前位置: 首页 > 知识库问答 >
问题:

ElasticSearch仅返回具有不同值的文档

翁和正
2023-03-14

假设我有这个给定的数据

{
            "name" : "ABC",
            "favorite_cars" : [ "ferrari","toyota" ]
          }, {
            "name" : "ABC",
            "favorite_cars" : [ "ferrari","toyota" ]
          }, {
            "name" : "GEORGE",
            "favorite_cars" : [ "honda","Hyundae" ]
          }

当我搜索最喜欢丰田车的人时,每当我查询这个数据时,它都会返回这个数据

{

            "name" : "ABC",
            "favorite_cars" : [ "ferrari","toyota" ]
          }, {
            "name" : "ABC",
            "favorite_cars" : [ "ferrari","toyota" ]
          }

结果是两个名为ABC的记录。如何只选择不同的文档?我想得到的结果只有这个

{
                "name" : "ABC",
                "favorite_cars" : [ "ferrari","toyota" ]
              }

这是我的问题

{
    "fuzzy_like_this_field" : {
        "favorite_cars" : {
            "like_text" : "toyota",
            "max_query_terms" : 12
        }
    }
}

我正在使用ElasticSearch 1.0.0。使用java api客户端

共有3个答案

宿衡虑
2023-03-14

@JRL几乎是正确的。您需要在查询中进行聚合。这将为您提供对象中按发生顺序排序的前10000个“favorite_cars”的列表。

{
    "query":{ "match_all":{ } },
    "size":0,
    "Distinct" : {
        "Cars" : {
            "terms" : { "field" : "favorite_cars", "order": { "_count": "desc"}, "size":10000 }
         }
    }
}

还值得注意的是,为了得到“迈凯轮F1”而不是“迈凯轮”、“F1”,您不希望对“favorite_car”字段进行分析。

"favorite_car": {
    "type": "string",
    "index": "not_analyzed"
}
赵炯
2023-03-14

ElasticSearch不提供任何查询,您可以通过该查询根据字段值获取不同的文档。

理想情况下,您应该为具有相同类型和id的同一文档编制索引,因为ElasticSearch使用这两件事为文档提供唯一id。唯一id很重要,这不仅是因为它可以检测重复文档,还可以在进行任何修改时更新同一文档,而不是插入新文档。有关索引文档的更多信息,请阅读本文。

但肯定有解决你问题的办法。由于您使用的是java api客户端,因此可以根据字段值自行删除重复文档。事实上,它使您能够更灵活地对从ES获得的响应执行自定义操作。

SearchResponse response = client.prepareSearch().execute().actionGet();
SearchHits hits = response.getHits();

Iterator<SearchHit> iterator = hits.iterator();
Map<String, SearchHit> distinctObjects = new HashMap<String,SearchHit>();
while (iterator.hasNext()) {
    SearchHit searchHit = (SearchHit) iterator.next();
    Map<String, Object> source = searchHit.getSource();
    if(source.get("name") != null){
        distinctObjects.put(source.get("name").toString(),source);
    }

} 

因此,您的地图中将有一个独特的searchHit对象地图。

您还可以创建一个对象映射,并使用它代替SearchHit。

我希望这能解决你的问题。如果代码中有任何错误,请原谅我。这只是一个伪代码,让你明白如何解决你的问题。

谢谢

容修贤
2023-03-14

您可以使用聚合消除重复。使用术语聚合,结果将按一个字段分组,例如name,还提供字段每个值出现的计数,并按此计数(降序)对结果进行排序。

{
  "query": {
    "fuzzy_like_this_field": {
      "favorite_cars": {
        "like_text": "toyota",
        "max_query_terms": 12
      }
    }
  },
  "aggs": {
    "grouped_by_name": {
      "terms": {
        "field": "name",
        "size": 0
      }
    }
  }
}

除了命中之外,结果还将包含,其唯一值在key中,计数在doc_count中:

{
  "took" : 4,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.19178301,
    "hits" : [ {
      "_index" : "pru",
      "_type" : "pru",
      "_id" : "vGkoVV5cR8SN3lvbWzLaFQ",
      "_score" : 0.19178301,
      "_source":{"name":"ABC","favorite_cars":["ferrari","toyota"]}
    }, {
      "_index" : "pru",
      "_type" : "pru",
      "_id" : "IdEbAcI6TM6oCVxCI_3fug",
      "_score" : 0.19178301,
      "_source":{"name":"ABC","favorite_cars":["ferrari","toyota"]}
    } ]
  },
  "aggregations" : {
    "grouped_by_name" : {
      "buckets" : [ {
        "key" : "abc",
        "doc_count" : 2
      } ]
    }
  }
}

注意,由于重复消除和结果排序,使用聚合的成本将很高。

 类似资料:
  • 我试图解决一个问题,我必须在搜索中得到明确的结果。 当我对最喜欢的汽车“法拉利”执行术语查询时。我得到两个名为ABC的结果。在这种情况下,我只是希望返回的结果应该是一个。所以我的要求是,如果我可以应用一个不同的on name字段来接收一个1结果。 谢啦

  • 问题内容: 我有一个看起来像这样的架构: 我想找到b的所有值,其中b的值由2个或更多实体共享: 查询依据: 应该返回和。 问题答案: 您可以使用2 的字段对字段进行聚合,然后添加子聚合以找到匹配的字段:

  • 问题内容: 我有以下查询: 这将同时返回“匹配”对象(整个文档)和“ inner_hits”对象(嵌套在匹配内部)。 有没有办法让我只返回出现在“ inner_hits”结果中的匹配“查询”元素,而没有获取整个文档? 问题答案: 应该可以通过以下方式 在顶层 禁用source- field 来实现

  • elasticsearch实例的一些背景: 一个节点,在一台机器上 特定索引由大小为1.23TB的26亿文档组成 索引被分成4个碎片。 堆大小设置为30 GB 服务器有256GB内存和40个内核。 Elasticsearch(版本1.4.3)是这个服务器上唯一运行的东西 我想返回所有具有特定名称的文档。属性名称已映射为: 我尝试过使用不同类型的搜索;过滤器、查询字符串、术语。结果都一样。当前查询如

  • 问题内容: 我想将查询发送给ELS,该查询仅返回总点击数。 没有别的 就像我得到回应一样 我只想打印731552 现在我只发送: 卷曲http:// server:9200 / games_profilder / _search 谢谢 问题答案: 您可以为此使用响应过滤: 这将产生 如果您真的只想得到总数,则可以使用以下方法传递结果: 那只会产生数字

  • 问题内容: 搜索时,Elasticsearch返回包含各种元信息的数据结构。 实际结果集包含在从数据库返回的JSON结果内的“ hits”字段中。 Elasticsearch是否有可能仅返回所需的数据(然后是“ hits”字段的内容)而没有嵌入所有其他元数据中? 我知道我可以将结果解析为JSON并提取出来,但是我不希望复杂性,麻烦和性能下降。 谢谢! 这是Elasticsearch返回的数据结构的