将纬度和经度导入 Solr 中的位置(LatLonPointSpatialField class)字段

Importing latitude and longitude into a location(LatLonPointSpatialField class) field in Solr

好的,我正在寻找有关如何导入包含以下字段的 CSV 文件的一般指南

poi_name, latitude, longitude

进入 Solr (7.x) 核心来执行地理查询?实现这一目标的正确方法是什么?我试过了

我真的需要麻烦定义一个 DataImportHandler 来执行此操作,还是为所有这些创建一个架构就足够了?

如果纬度和经度已经存在并且我稍后尝试使用位置字段更新架构怎么办?

找不到这样做的好例子,但是有一个旧的例子,如果纬度和经度有预定义的名称,后缀类似于 location_1_coordinatelocation 字段会自动组成location_2_coordinate 这看起来很傻!

首先 - 您必须定义一个位置字段。无模式模式用于快速原型制作,如果您需要更具体的字段(并确保这些字段在生产中获得正确的类型),则必须明确配置它们。为此使用 the LatLonPointSpatialField type,并使其成为单值。

首先定义要使用的字段类型(这些是adopted from the Schema API documentation):

curl -X POST -H 'Content-type:application/json' --data-binary '{   "add-field-type" : {
     "name":"location_type",
     "class":"LatLonPointSpecialField"

}' http://localhost:8983/solr/gettingstarted/schema

然后添加该类型的字段:

curl -X POST -H 'Content-type:application/json' --data-binary '{
  "add-field":{
     "name":"location",
     "type":"location_type",
     "stored":true }
}' http://localhost:8983/solr/gettingstarted/schema

另外两个问题可以通过 custom update chain 解决(您在索引文档时提供链的名称作为 update.chain URL 参数)。

要自动将 GUID 分配给任何索引文档,您可以使用 UUIDUpdateProcessorFactory。将字段名称 (id) 作为 fieldName 参数。

要将纬度和经度连接到以 , 作为分隔符的单个字段,您可以使用 ConcatFieldUpdateProcessorFactory. The important thing here is that it concatenates a list of values given for a single valued field into a single value - it does not concatenate two different field names. To fix that we can use a CloneFieldUpdateProcessor 将纬度和经度值移动到一个单独的字段中。

<updateRequestProcessorChain name="populate-location">
  <processor class="solr.CloneFieldUpdateProcessorFactory">
    <arr name="source">
      <str>latitude</str>
      <str>longitude</str>
    </arr>
    <str name="dest">location</str>
  </processor>
  <processor class="solr.ConcatFieldUpdateProcessorFactory">
    <str name="delimiter">,</str>
  </processor>
</updateRequestProcessorChain

如果您稍后添加位置字段并且数据库中已有数据,这将不起作用。 Solr 不会触及已经索引的数据,您必须重新索引才能以正确的方式处理和索引您的信息。无论您如何将内容放入 location 字段,都是如此。

旧的示例可能是另一种方式 - 早些时候你会发送一对 latlon,它会被索引为两个单独的值 - 一个用于纬度,一个用于经度 - 在引擎盖下。您可能可以通过为每个值发送一个值来解决这个问题,但这实际上是为了以相反的方式工作——发送一个值并将其作为两个单独的字段编入索引。由于 Lucene(和 Solr)中的地理空间支持刚刚起步,因此重新使用了已经存在的类型,而不是创建更多专用类型。

只需总结并汇总所有感兴趣的人的答案,这是我按照 MatsLindh 的建议得出的解决方案。上下文:CentOS 7 和 Solr 7.5

  • Sample.csv内容

name,lon,lat, A,22.9308852,39.3724824 B,22.5094530,40.2725792


  • 架构的相关部分(managed-schema 文件)

<fieldType name="location" class="solr.LatLonPointSpatialField" docValues="true"/> ... <field name="lat" type="string" omitTermFreqAndPositions="true" indexed="true" required="true" stored="true"/> <field name="location" type="location" multiValued="false" stored="true"/> <field name="lon" type="string" omitTermFreqAndPositions="true" indexed="true" stored="true"/>


  • solrconfig.xml
<updateRequestProcessorChain name="uuid-location">
      <processor class="solr.UUIDUpdateProcessorFactory">
        <str name="fieldName">id</str>
      </processor>
        <processor class="solr.CloneFieldUpdateProcessorFactory"> 
            <str name="source">lat</str> 
            <str name="dest">location</str> 
        </processor> 
        <processor class="solr.CloneFieldUpdateProcessorFactory"> 
            <str name="source">lon</str> 
            <str name="dest">location</str> 
        </processor> 
       <processor class="solr.ConcatFieldUpdateProcessorFactory"> 
            <str name="fieldName">location</str> 
            <str name="delimiter">,</str> 
        </processor>
      <processor class="solr.LogUpdateProcessorFactory"/>
      <processor class="solr.RunUpdateProcessorFactory" />
     </updateRequestProcessorChain>
  <initParams path="/update/**,/query,/select,/tvrh,/elevate,/spell,/browse">
    <lst name="defaults">
      <str name="df">_text_</str>
      <str name="update.chain">uuid-location</str>
    </lst>
  </initParams>

并在bash

中将示例文件导入核心运行以下

/opt/solr/bin/post -c your_core_name /opt/solr/sample.csv


如果您想知道如何查询该数据,请使用

http://localhost:8983/solr/your_core_name/select?&q=*:*&fq={!geofilt%20sfield=location}&pt=42.27,-74.91&d=1

其中 pt 是经纬度点,d 是以千米为单位的距离。