如何保留我的距离表示分数字段并将其映射到我的结果实体中?

Posted

技术标签:

【中文标题】如何保留我的距离表示分数字段并将其映射到我的结果实体中?【英文标题】:How can I keep my, distance representing, score field and map it into my resulting entity? 【发布时间】:2019-12-07 19:28:51 【问题描述】:

我正在使用以下查询:

NativeSearchQuery nsq = new NativeSearchQueryBuilder()
    .withQuery(qb)
    .withPageable(PageRequest.of(page, PAGE_SIZE))
    .withSort(sb)
    .build();

使用以下 SortBuilder:

SortBuilders.geoDistanceSort("customer.address.geoLocation",
         customer.getAddress().getGeoLocation().toGeoPoint())
    .order(SortOrder.ASC)
    .unit(DistanceUnit.KILOMETERS);

产生所需的排序查询:

"sort": [
  
    "_geo_distance" : 
      "customer.address.geoLocation" : [
        
          "lat" : 40.4221663,
          "lon" : -3.7148336
        
      ],
      "unit" : "km",
      "distance_type" : "arc",
      "order" : "asc",
      "validation_method" : "STRICT",
      "ignore_unmapped" : false
    
  
]

另外,每个生成的文档都将距离返回到以 km 为单位的参考参数:

"sort": [2.4670609224864997]

我需要这个值作为我的域的一部分,但我根本无法将它推送到我的对象中。我尝试了一种简单的方法,将其定义到我的域中,就像float[] 一样,但我一直为空。我正在使用 Jackson 进行(反)序列化。

  private float[] sort;

  public float[] getSort() 
    return this.sort;
  

  public void setSort(float[] score) 
    this.sort = score;
  

我的仓库:

  public interface ElasticsearchProductRepository 
        extends ElasticsearchRepository<Product, String> 
    Page<Product> search(SearchQuery searchQuery);
  

产品:

@Entity
@Table(name = "product")
@Document(indexName = "product", createIndex = true, type = "_doc")
@Setting(settingPath = "elasticsearch/product-index.json")
@DynamicTemplates(mappingPath = "elasticsearch/product-dynamic-templates.json")
public class Product 

...

  @org.springframework.data.annotation.Id
  @javax.persistence.Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @JsonView(ResponseView.class)
  private long id;

  @Field(analyzer = "autocomplete", type = FieldType.Text, searchAnalyzer="standard")
  @JsonView(CreationRequestView.class)
  private String productName;
  private float[] sort;

...

  public float[] getSort() 
    return this.sort;
  

  public void setSort(float[] score) 
    this.sort = score;
  


我添加了以下脚本字段:

  "script_fields": 
    "distance": 
      "script": 
        "lang":   "painless",
        "source": "doc['sort']",
        "params": 
        
      
    


但它没有找到排序字段。

"reason": "No field found for [sort] in mapping with types []"

似乎 doc 在现实中引用了 doc._source ......我如何从 Elastic 脚本中引用这么多的数据?

【问题讨论】:

你能添加你的Product类的定义吗? 添加了相关部分。 【参考方案1】:

目前在 Spring Data Elasticsearch 中,返回的实体由 _source 字段中返回的值填充。返回的 sort 不是其中的一部分,而是为每个搜索命中返回的附加信息的一部分。

对于下一个版本 (4.0),我们目前正在重写如何处理返回的命中。下一个版本将有一个SearchHit&lt;T&gt; 类,其中T 是实体域类,SearchHit 对象包含该实体以及其他信息,如分数、突出显示、脚本字段、排序等。

计划存储库方法然后可以返回这些SearchHit 对象的列表或页面。

但目前,查询的排序将导致排序返回,但您无法自行检索排序值 - 在您的情况下这很糟糕,因为它们是动态计算的。

编辑:

您可以通过在实体中为 geo_distance 定义一个属性并使用 @ScriptedField 注释对其进行注释来检索该值,然后在您的本机查询中提供脚本。可以在tests for Spring Data Elasticsearch 中找到一个示例。此示例适用于 ElaticsearchTemplate,但将此查询传递给存储库搜索方法应该没有区别。

编辑 25.12.2019:

当前的 master 分支将成为 Spring Data Elasticsearch 4.0,已实现此功能。找到的文档将在还包含 sortValuesSearchHit 对象中返回。

【讨论】:

感谢您的清晰解释。例如,有什么方法可以将距离值编写到我的 _source 字段中以将其解析为实体?我会同时关注 4.0。 更新了我的原始问题,我似乎无法从脚本字段脚本中引用此字段。 替代方案是doc['customer.address.geoLocation'].planeDistance(33.818445,-84.555139),但我似乎要计算两次距离,一次进行排序,一次进行字段。 在这样做的同时,其余的 _source 也消失了,并且找不到任何与我的 nativequery 类似的 spring-data 等效项:“fields”:[“_source”] 没有什么对我有用,我最终复制并扩展了 DefaultResultsMapper 并将其注入到我的 ElasticsearchRestTemplate 的构造函数中;然后对我的课程进行硬编码。

以上是关于如何保留我的距离表示分数字段并将其映射到我的结果实体中?的主要内容,如果未能解决你的问题,请参考以下文章

Cakephp 1.3:如何迁移到我的文章标签 - 功能

如何从我的 phpmyadmin 表中复制一列并将其粘贴到我的 Excel 工作表中?

如何将提及变量转换为普通变量并将其打印到我的终端

如何访问我抓取的值并将其添加到我的 DataGrid?请看截图

如何以编程方式从照片应用程序中检索所有照片/视频并将其复制到我的应用程序?

如何捕获 kivy-client 崩溃日志并将其发送到我的服务器?