Sprężysta guma : Jak prawidłowo korzystać z pola podrzędne?

0

Pytanie

Jestem zupełnie początkujący w ElasticSearch. Pracuję nad projektem, w którym musimy znaleźć obiekt (Oferta), zawierający zestaw dwóch (tłumaczenie zdań). Celem jest, aby przeprowadzić badanie na podstawie niektórych pól zdań, a także wielu pól przetłumaczonych zdań. Oto skrócona wersja obu klas :

Offer.class (zwróć uwagę, że ja аннотировал zestaw z pomocą @Field(typ= FieldType.Nested), abym mógł wykonywać podzapytania, jak podano w oficjalnym dokumencie) :

@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;
}

Oczekiwane zachowanie będzie polegała na tym, że mogę tworzyć podzapytania jako takie :

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

Ale dostaję wyjątek : nie można utworzyć zapytania: [załącznik] zagnieżdżony obiekt na drodze [Propozycje] nie ma załącznika typu"

EDIT : mogę uzyskać dostęp do ofert.język.kod z użyciem zwykłych zapytań (co tak naprawdę mnie nie przeszkadza). Ale nadal nie do końca rozumiem.

Moje zestawienie mówi, że pola, oferujące tłumaczenia, nie mają podrzędnego rodzaju, jak widać wyżej, ale ponieważ użyłem @Field(typ = FieldType.Nested), ja naprawdę nie rozumiem takiego zachowania. Może ktoś wyjaśnić?

{
  "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"
            }
          }
        }
      }
    }
  }
}
2

Najlepsza odpowiedź

1

Jak powstało zestawienie indeksów? To nie wygląda na to, że Spring Data Elasticsearch napisał to zestawienie. Nowy typ offerTranslations nie ma, jak widać, i pola tekstowe mają .keyword подполе. To wygląda tak, jakby dane były wstawiane do indeksu bez określonego skojarzenia, a więc Elasticsearch wykonał automatyczne mapowanie. W tym przypadku znaczenia @Field adnotacje nie są używane.

Trzeba, aby Spring Data Elasticsearch stworzył indeks z mapowaniem. Stanie się to automatycznie, jeśli indeks nie istnieje, i korzystasz z repozytorium Spring Data Elasticsearch, lub musisz użyć IndexOperations.createWithMapping funkcja w aplikacji.

Jeszcze jedna rzecz, którą zauważyłem: wygląda na to, że korzystasz z tego samego klasa encji dla różnych magazynów danych Spring, mocno mieszając adnotacje. Trzeba korzystać z różnych encji dla różnych sklepów.

2021-11-22 17:12:04

Próbowałem usunąć mapowanie za pomocą kibana : USUNĄĆ oferta/_mapping i переиндексировать moje propozycje. Ale, być może, zastosowanie jawnego "createWithMapping" może działać lepiej, dam ci znać, jeśli to pomoże ! W każdym razie, dziękuję ci
Aymane EL Jahrani

Witam, więc próbowałem użyć funkcji createWithMapping, ale to nie wydaje się proste. Czy możesz potwierdzić, że jest to właściwy sposób jego użycia ? github.com/spring-projects/spring-data-elasticsearch/blob/main/...
Aymane EL Jahrani
0

KROKI DO ROZWIĄZANIA :

  • Użyj Kibana, aby upewnić się, że USUNIĘTO <nazwa_indeksu>/_mapping
  • Poszukaj w swoich klasach encji terminach obiekty, które mogą znajdować się w właściwościach @JsonIgnoreProperties
  • Upewnij się, że chętnie pobrać atrybuty relacji ToMany (w przeciwnym razie elastic nie stworzy dopasowanie do danych, które nigdy nie oferowali).
  • Wychodząc z tego niewielkiego doświadczenia, ja bym powiedział, że należy unikać stosowania zagnieżdżonych pól, nie widziałem w ich użyciu żadnych korzyści. Więc sprawdź, czy tak jest i dla ciebie !
2021-11-25 23:17:34

Spring Data Elasticsearch nic nie robi z @JsonIgnoreProperties streszczenie. Elasticsearch nie jest relacyjna baza danych, i nie ma pojęcia o relacji między encjami.
P.J.Meisch

To prawda, ale spring robi to przy serializacji danych. Oto jak dostaję swoje encji ...
Aymane EL Jahrani

Sama wiosna tego nie robi. Na przykład, JPA, Spring Data to robi. Spring Data Elasticsearch tego nie robi. Są to różne moduły danych Spring.
P.J.Meisch

Biblioteka fasterxml.jackson robi to ,i działa z użyciem adnotacji dla obiektów JPA/Hibernate. To, że używam w tym projekcie, jak widać w moim kodzie...
Aymane EL Jahrani

W innych językach

Ta strona jest w innych językach

Русский
..................................................................................................................
Italiano
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................