Поиск в гибернации по встроенному составному первичному ключу - PullRequest
0 голосов
/ 04 августа 2020

У меня есть класс UserAdAccountId, определенный как встроенный класс идентификатора. Используя этот класс id, я определил класс UserAdAccount и использовал двусторонний мост строковых полей для составного первичного ключа. Затем я попытался выполнить поиск в спящем режиме в классе Entity AdAccount, но столкнулся с этим исключением: Не удалось найти поле userAdAccounts.id.userId в AdAccount.

Как видите, я пропустил userAdAccounts.id .userId "в качестве пути к полю onField (), поскольку userAdAccounts - это набор UserAdAccount. Идентификатор UserAdAccount имеет тип UserAdAccountId, в котором в качестве полей указаны как userId, так и adAccountId. Я использовал @IndexedEmbedded (includeEmbeddedObjectId = true), чтобы убедиться, что этот идентификатор типа UserAdAccountId включен в индексирование.

Мой вопрос в том, почему я все еще вижу эту ошибку неправильного пути к полю?

@Indexed
@Embeddable
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = {"userId", "adAccountId"})
@ToString
public class UserAdAccountId implements Serializable {

    @Column(name = "USER_ID")
    @GenericGenerator( name = "native", strategy = "native")
    @Field
    private Long userId;

    @Column(name = "AD_ACCOUNT_ID")
    @GenericGenerator( name = "native", strategy = "native")
    @Field
    private Long adAccountId;

}

@Entity (name = "JHI_USER_AD_ACCOUNT")
@Indexed
@Getter
@Setter
public class UserAdAccount implements SearchableEntity, Serializable {

    @EmbeddedId
    @DocumentId
    @FieldBridge(impl = UserAdAccoutPrimaryKeyBridge.class)
    @IndexedEmbedded(includePaths = {"userId"})
    private UserAdAccountId id;

    @ManyToOne
    @JoinColumn(name = "USER_ID", referencedColumnName = "ID", updatable = false, insertable = false)
    private User user;

    @ManyToOne
    @JoinColumn(name = "AD_ACCOUNT_ID", referencedColumnName = "ID", updatable = false, insertable = false)
    private AdAccount adAccount;

}

@Entity
@Indexed
@Table(name = "AD_ACCOUNT")
@Getter
@Setter
@ToString
public class AdAccount implements SearchableEntity, Serializable {
    @Id
    @DocumentId
    @SortableField
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.AUTO, generator="native")
    @GenericGenerator( name = "native", strategy = "native")
    private Long id;

    @IndexedEmbedded(includeEmbeddedObjectId = true)
    @OneToMany(mappedBy = "adAccount", fetch = FetchType.LAZY)
    private Set<UserAdAccount> userAdAccounts = new HashSet<>();
}

Журнал поиска в гибернации c Я реализовал:

if(this.searchRequest.getExactMatchFilters().containsKey("userId")) {
    Set<String> userIds = this.searchRequest.getExactMatchFilters().get("userId");
    BooleanJunction<BooleanJunction> combined = queryBuilder.bool();
    combined.minimumShouldMatchNumber(1);
    for(String userId : userIds) {
        combined.should(queryBuilder.keyword().onField("userAdAccounts.id.userId").matching(userId).createQuery());
    }
    filters.add(combined.createQuery());
}

Обновление: О ошибка отображения динамического c с двухсторонним полевым мостом. Я нашел это в официальной документации: Я нашел это в официальной документации:

Когда ваш MetadataProvidingFieldBridge регистрирует поле, имя которого является именем существующего поля, с добавленной точкой и другой строкой, например name + " .mySubField ", Hibernate Search переведет его как объект со свойством mySubField в документе JSON, отправленном в Elasticsearch.

В результате подполя могут иметь только родительское поле с типом OBJECT: очевидно, Elasticsearch отклонит String или Integer со свойством mySubField. Поэтому каждый раз, когда регистрируется поле с именем foo.bar, его родительское поле foo должно быть зарегистрировано с типом OBJECT, как в следующем примере. Если этого не сделать, это приведет к ошибкам, когда Hibernate Search генерирует схему Elasticsearch.

Итак, в моем случае я сделал следующее. Мне, вероятно, следует зарегистрировать идентификатор с типом объекта, а также изменить USER_ID_SUFFIX на .userId и AD_ACCOUNT_ID_SUFFIX на .adaccountId?

private static final String USER_ID_SUFFIX = "_userId";
private static final String AD_ACCOUNT_ID_SUFFIX = "_adaccountId";

@Override
public void configureFieldMetadata(String id, FieldMetadataBuilder builder) {
    builder.field(id + USER_ID_SUFFIX, FieldType.LONG)
            .field(id + AD_ACCOUNT_ID_SUFFIX, FieldType.LONG);
}

1 Ответ

0 голосов
/ 04 августа 2020

Вы просто не сопоставили поле userAdAccounts.id.userId. Вы сопоставили поле userAdAccounts.id, и на этом все. Hibernate Search добавит в документы AdAccount только поле с именем userAdAccounts.id типа String. Hibernate Search, как правило, не добавляет поля, которые вы не просили добавить.

Если вы также хотите добавить отдельное поле для userId:

  • Либо используйте реализацию TwoWayFieldBridge, которую я упомянул в моем ответе на ваш другой вопрос
  • , либо добавьте @IndexedEmbedded к UserAdAccount.id и @Field к UserAdAccountId.userId.
...