簡體   English   中英

Spring 彈性:使用嵌套字段的正確方法是什么?

[英]Spring elastic : What is the correct way of using nested fields?

我對 ElasticSearch 很陌生。 我正在做一個項目,我們需要搜索包含一組兩個(OfferTranslation)的 object(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<>();


}

報價翻譯.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;
}

預期的行為是我可以這樣進行nestedQueries:

QueryBuilder qBuilder = nestedQuery("offersTranslations",boolQuery().must(termQuery("offersTranslations.language.code",language)), ScoreMode.None);

但我得到的是一個例外:未能創建查詢:[nested] 路徑 [offersTranslations] 下的嵌套 object 不是嵌套類型”

編輯:我可以使用普通查詢訪問 offerTranslations.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"
            }
          }
        }
      }
    }
  }
}

索引映射是如何創建的? 它看起來不像 Spring 數據 Elasticsearch 寫了這個映射。 如您所見, offerTranslations的嵌套類型缺失,並且文本字段有一個.keyword子字段。 這看起來像是在沒有定義映射的情況下將數據插入索引,因此 Elasticsearch 進行了自動映射。 在這種情況下,不使用@Field注釋的值。

您需要讓 Spring 數據 Elasticsearch 使用映射創建索引。 如果索引不存在並且您正在使用 Spring 數據 Elasticsearch 存儲庫,這將自動發生,或者您需要在應用程序中使用IndexOperations.createWithMapping ZC1C425268E68385D1AB5074C17A94F14。

我注意到的另一件事:似乎您對不同的 Spring 數據存儲使用相同的實體 class ,大量混合注釋。 您應該為不同的商店使用不同的實體。

解決步驟:

  • 使用 Kibana 確保刪除 <index_name>/_mapping
  • 在您的實體類中查找您需要的對象,這些對象可能在 @JsonIgnoreProperties 中
  • 確保您急切地加載您的 toMany 關系的屬性(否則彈性不會為您從未提供的數據創建映射)
  • 根據這個小小的經驗,我會說避免使用嵌套字段,我看不出使用它們有什么好處。 因此,請檢查您是否也是這種情況!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM