【问题标题】:Spring Data Elasticsearch with ES 7.2.1 | GeoPoint mapping failure while indexing带有 ES 7.2.1 的 Spring Data Elasticsearch |索引时 GeoPoint 映射失败
【发布时间】:2020-04-14 20:03:11
【问题描述】:

我正在使用 ES 7.2.1 存储大量基于位置的数据并查询附近的位置。 对于位置坐标,我使用的是 java 代码库中的 GeoPoint 字段。

ES:7.2.1
Spring Data Elasticsearch:4.0.0.DATAES-690-SNAPSHOT
MVN org.elasticsearch:7.2.1

模板:

curl -X PUT "localhost:9200/_template/store_locator_template?pretty"
{
  "order": 1,
  "index_patterns": [
    "store_locator_*"
  ],
  "settings": {
  },
  "mappings": {
      "properties": {
      "esId": {
        "type": "keyword"
      },
      "geoPoint": {
        "type": "geo_point"
      },
      "storeName": {
        "type": "keyword"
      }
    }
  }
}

当尝试通过 bulkIndex() 插入数据时,我收到此错误:

org.springframework.data.elasticsearch.ElasticsearchException: 
Bulk indexing has failures. Use ElasticsearchException.getFailedDocuments() 
for detailed messages [{QObQeXEBqxAg6uMFyeNZ=ElasticsearchException
[Elasticsearch exception 
[type=illegal_argument_exception, reason=
mapper [geoPoint] of different type, 
current_type [geo_point], merged_type [ObjectMapper]]]}]

实体:

@Getter
@Setter
@ToString
@EqualsAndHashCode(of = "esId", callSuper = false)
@NoArgsConstructor
@Document(indexName = "store_locator_index", replicas = 0, createIndex = false)
public class EsEntity {

  @Id
  @Field(type = FieldType.Text)
  private String esId;

  @GeoPointField
  private GeoPoint geoPoint;

  @Field(type = FieldType.Text)
  private String storeName;
}

更新: 如果我使用下面的代码,它工作正常。它根据需要放置映射,并且 spring data es 不会抱怨!

//clazz -> entity class with @Document annotation

boolean indexCreated = false;
if (!elasticsearchOperations.indexExists(clazz)) {
    indexCreated = elasticsearchOperations.createIndex(clazz);
}
if (indexCreated) {
    elasticsearchOperations.refresh(clazz);
    elasticsearchOperations.putMapping(clazz);   --> Does the MAGIC
}

...而上面代码生成的映射是:

{
   "esentity":{              ---> Why is this here??
      "properties":{
         "esId":{
            "type":"keyword",
            "index":true
         },
         "geoPoint":{
            "type":"geo_point"
         }
      }
   }
}

它正在以我的实体类的名称向映射添加一个类型!

=====================
还有.....

一切似乎都在为:
ES:6.4.3
Spring Data Elasticsearch:3.1.X

我能够(通过模板)插入带有 GeoPoint 字段的文档。 通过代码插入文档时会自动生成索引。 同一组代码运行良好,没有错误!!!!

这是我的模板:

curl -X PUT "localhost:9200/_template/store_locator_template?pretty"
{
  "order": 1,
  "index_patterns": [
    "store_locator_*"
  ],
  "settings": {
  },
  "mappings": {
    "store_locator_index": {
      "properties": {
      "esId": {
        "type": "keyword"
      },
      "geoPoint": {
        "type": "geo_point"
      },
      "storeName": {
        "type": "keyword"
      }
    }
   }
  }
}

这是映射:

{
  "mapping": {
    "properties": {
      "esId": {
        "type": "keyword"
      },
      "geoPoint": {
        "type": "geo_point"
      }
    }
  }
}

【问题讨论】:

  • 你能分享一下你的实体类的代码吗?
  • @P.J.Meisch 已更新!

标签: java spring spring-data spring-data-elasticsearch elasticsearch-7


【解决方案1】:

您显示的代码中有些内容不匹配:

在您显示的第一个模板中,您将 storeName 定义为 keyword 类型,但在实体上,您将其类型为 text

带有@Id 注释的字段始终是keyword 类型,将其定义为text 类型的@Field 注释将被忽略。

我使用了以下版本:ES 7.3.0(我的机器上没有 7.2.1),Spring Data 4.0 当前主版本,客户端库设置为 7.3.0。

当我没有定义模板,但使用您显示的代码创建索引时:

    boolean indexCreated = false;

    Class<EsEntity> clazz = EsEntity.class;
    if (!elasticsearchOperations.indexExists(clazz)) {
        indexCreated = elasticsearchOperations.createIndex(clazz);
    }
    if (indexCreated) {
        elasticsearchOperations.refresh(clazz);
        elasticsearchOperations.putMapping(clazz);
    }

我得到以下索引:

{
  "store_locator_index": {
    "aliases": {},
    "mappings": {
      "properties": {
        "esId": {
          "type": "keyword"
        },
        "geoPoint": {
          "type": "geo_point"
        },
        "storeName": {
          "type": "text"
        }
      }
    },
    "settings": {
      "index": {
        "refresh_interval": "1s",
        "number_of_shards": "1",
        "provided_name": "store_locator_index",
        "creation_date": "1587073075464",
        "store": {
          "type": "fs"
        },
        "number_of_replicas": "0",
        "uuid": "72aZqWDtS7KLDMwdkgVtag",
        "version": {
          "created": "7030099"
        }
      }
    }
  }
}

映射看起来应该,映射中没有没有类型信息(这是使用ES 6时由Spring Data Elasticsearch 3.2版本编写的,但我不再使用了)

当我添加您显示的模板,然后使用以下代码进行批量插入时:

    EsEntity es1 = new EsEntity();
    es1.setEsId("1");
    es1.setGeoPoint(new GeoPoint(12, 34));
    es1.setStoreName("s1");
    IndexQuery query1 = new IndexQueryBuilder().withId("1").withObject(es1).build();

    EsEntity es2 = new EsEntity();
    es2.setEsId("2");
    es2.setGeoPoint(new GeoPoint(56, 78));
    es2.setStoreName("s2");
    IndexQuery query2 = new IndexQueryBuilder().withId("2").withObject(es2).build();

    elasticsearchOperations.bulkIndex(Arrays.asList(query1, query2), IndexCoordinates.of("store_locator_index"));

然后创建以下索引(注意 store_name 的类型为 keywordnow,来自模板):

{
  "store_locator_index": {
    "aliases": {},
    "mappings": {
      "properties": {
        "_class": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "esId": {
          "type": "keyword"
        },
        "geoPoint": {
          "type": "geo_point"
        },
        "storeName": {
          "type": "keyword"
        }
      }
    },
    "settings": {
      "index": {
        "creation_date": "1587073540386",
        "number_of_shards": "1",
        "number_of_replicas": "1",
        "uuid": "LqzXMC5uRmKmImIzblFBOQ",
        "version": {
          "created": "7030099"
        },
        "provided_name": "store_locator_index"
      }
    }
  }
}

两个文档按原样插入:

{
  "took": 22,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 1.0,
    "hits": [
      {
        "_index": "store_locator_index",
        "_type": "_doc",
        "_id": "1",
        "_score": 1.0,
        "_source": {
          "_class": "com.sothawo.springdataelastictest.EsEntity",
          "esId": "1",
          "geoPoint": {
            "lat": 12.0,
            "lon": 34.0
          },
          "storeName": "s1"
        }
      },
      {
        "_index": "store_locator_index",
        "_type": "_doc",
        "_id": "2",
        "_score": 1.0,
        "_source": {
          "_class": "com.sothawo.springdataelastictest.EsEntity",
          "esId": "2",
          "geoPoint": {
            "lat": 56.0,
            "lon": 78.0
          },
          "storeName": "s2"
        }
      }
    ]
  }
}

所以我在代码中找不到错误,但是如果有冲突的条目,您应该检查模板和现有索引。

【讨论】:

  • 谢谢。 storeName 是文本,在发布问题时,我以某种方式将其错误地编辑为关键字。
猜你喜欢
  • 2019-07-04
  • 2012-08-31
  • 1970-01-01
  • 2017-05-18
  • 1970-01-01
  • 1970-01-01
  • 2017-07-07
  • 2021-11-03
  • 2014-04-15
相关资源
最近更新 更多