我對 ElasticSearch 很陌生。我正在處理一個專案,我們需要在其中搜索包含一組兩個 (OfferTranslation) 的物件 (Offer)。目標是基于一些Offer欄位進行研究,但也有很多OfferTranslation欄位。這是兩個類的縮小版本:
Offer.class (請注意,我使用 @Field(type= FieldType.Nested) 對 Set 進行了注釋,因此我可以進行嵌套查詢,如官方檔案中所述):
@org.springframework.data.elasticsearch.annotations.Document(indexName = "offer")
@DynamicMapping(DynamicMappingValue.False)
public class Offer implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
@Field(type = FieldType.Long)
private Long id;
@OneToMany(mappedBy = "offer", targetEntity = OfferTranslation.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@JsonIgnoreProperties(
value = { "pictures", "videos", "owner", "contexts", "offer", "personOfInterests", "followers" },
allowSetters = true
)
@Field(type = FieldType.Nested, store = true)
private Set<OfferTranslation> offersTranslations = new HashSet<>();
}
OfferTranslation.class :
@DynamicMapping(DynamicMappingValue.False)
public class OfferTranslation implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
@Field(type = FieldType.Long)
private Long id;
@NotNull
@Size(max = 100)
@Column(name = "title", length = 100, nullable = false)
@Field(type = FieldType.Text)
private String title;
@NotNull
@Size(max = 2000)
@Column(name = "summary", length = 2000, nullable = false)
@Field(type = FieldType.Text)
private String summary;
@Size(max = 2000)
@Column(name = "competitor_context", length = 2000)
@Field(type = FieldType.Text)
private String competitorContext;
@NotNull
@Size(max = 2000)
@Column(name = "description", length = 2000, nullable = false)
@Field(type = FieldType.Text)
private String description;
@NotNull
@Enumerated(EnumType.STRING)
@Column(name = "maturity", nullable = false)
@Field(type = FieldType.Auto)
private RefMaturity maturity;
@ManyToOne
@Field(type = FieldType.Object, store = true)
private RefLanguage language;
@NotNull
@Column(name = "created_at", nullable = false)
@Field(type = FieldType.Date)
private Instant createdAt;
}
預期的行為是我可以像這樣創建嵌套查詢:
QueryBuilder qBuilder = nestedQuery("offersTranslations",boolQuery().must(termQuery("offersTranslations.language.code",language)), ScoreMode.None);
但我得到的是一個例外:未能創建查詢:路徑 [offersTranslations] 下的 [嵌套] 嵌套物件不是嵌套型別”
編輯:我可以使用普通查詢訪問offersTranslations.language.code(目前并沒有真正打擾我)。但我還是不太明白。
我的映射表示欄位 offerTranslations 不是您在上面看到的嵌套型別,但是由于我使用了 @Field(type = FieldType.Nested) 我不太了解這種行為。 有人能解釋一下嗎?
{
"offer" : {
"mappings" : {
"properties" : {
"_class" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"categories" : {
"properties" : {
"id" : {
"type" : "long"
}
}
},
"criteria" : {
"properties" : {
"id" : {
"type" : "long"
}
}
},
"id" : {
"type" : "long"
},
"keywords" : {
"properties" : {
"id" : {
"type" : "long"
}
}
},
"offersTranslations" : {
"properties" : {
"competitorContext" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"createdAt" : {
"type" : "date"
},
"description" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"id" : {
"type" : "long"
},
"language" : {
"properties" : {
"code" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"id" : {
"type" : "long"
},
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"maturity" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"state" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"summary" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"title" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"updatedAt" : {
"type" : "date"
}
}
},
"units" : {
"properties" : {
"id" : {
"type" : "long"
}
}
}
}
}
}
}
uj5u.com熱心網友回復:
索引映射是如何創建的?看起來不像是 Spring Data Elasticsearch 寫的這個映射。offerTranslations如您所見,缺少嵌套型別 ,并且文本欄位有一個.keyword子欄位。這看起來像是在沒有定義映射的情況下將資料插入到索引中,因此 Elasticsearch 進行了自動映射。在這種情況下,@Field不使用注釋的值。
您需要讓 Spring Data Elasticsearch 創建帶有映射的索引。如果索引不存在并且您正在使用 Spring Data Elasticsearch 存盤庫,或者您需要IndexOperations.createWithMapping在應用程式中使用該功能,這將自動發生。
我注意到的另一件事:您似乎對不同的 Spring Data 存盤使用相同的物體類,大量混合注釋。您應該為不同的商店使用不同的物體。
uj5u.com熱心網友回復:
解決步驟:
- 使用 Kibana 確保 DELETE <index_name>/_mapping
- 在您的物體類中查找您需要的可能位于 @JsonIgnoreProperties 中的物件
- 確保您急切地加載您的 toMany 關系的屬性(否則彈性不會為您從未提供的資料創建映射)
- 從這個小小的經驗來看,我會說避免使用嵌套欄位,我看不出使用它們的任何優勢。因此,請檢查您是否也是這種情況!
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/366907.html
