У меня возникла проблема с реализацией логической логики с помощью Hibernate Search Filter. Есть люди, которые могут быть частью групп. Каждая группа имеет статус из каталога статуса.Фильтр Hibernate Search (Lucene) по коллекциям
Мне нужно отфильтровать всех пользователей, которые находятся в группе 1, и иметь статус 2. Для этого я использую логический запрос с Occur.MUST для обоих предложений, но в отфильтрованном результате включены люди, у которых есть список grops и один из них равен 1, а один из статусов группы 2, например:
person | group | status
105 (1) 3
105 2 3
105 3 (2)
188 (1) 3
188 7 (2)
197 (1) 4
197 8 5
197 9 (2)
пользователям 105, 188 и 197 не должны быть включены в отфильтрованный результат. Каков правильный способ добиться этого?
Фильтр:
BooleanQuery bq = new BooleanQuery();
TermQuery tqGroup = new TermQuery(new Term("groupPersons.id.groupId", "1"));
TermQuery tqStatus = new TermQuery(new Term("groupPersons.status.id", "2"));
bq.add(tqGroup, BooleanClause.Occur.MUST);
bq.add(tqStatus, BooleanClause.Occur.MUST);
filter = new QueryWrapperFilter(bq);
Person лицо:
...
private List<GroupPerson> groupPersons = new ArrayList<GroupPerson>(0);
@IndexedEmbedded
@OneToMany(fetch = FetchType.LAZY, mappedBy = "person")
public List<GroupPerson> getGroupPersons() {
return this.groupPersons;
}
GroupPerson лицо:
...
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "groupId", column = @Column(name = "group_id", nullable = false)),
@AttributeOverride(name = "personId", column = @Column(name = "person_id", nullable = false)) })
@NotNull
@DocumentId
@FieldBridge(impl = GroupPersonIdBridge.class)
public GroupPersonId getId() {
return this.id;
}
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "status_id",nullable = false)
@IndexedEmbedded
@NotNull
public Status getStatus() {
return this.Status;
}
OrganizationPersonIdBridge:
public Object get(String name, Document document) {
GroupPersonId id = new GroupPersonId();
Field field = document.getField(name + ".groupId");
id.setGroupId(Long.parseLong(field.stringValue()));
field = document.getField(name + ".personId");
id.setPersonId(Long.parseLong(field.stringValue()));
return id;
}
public String objectToString(Object object) {
GroupPersonId id = (GroupPersonId) object;
StringBuilder sb = new StringBuilder();
sb.append(id.getGroupId())
.append(" ")
.append(id.getPersonId());
return sb.toString();
}
public void set(String name,Object value,Document document,LuceneOptions luceneOptions) {
GroupPersonId id = (GroupPersonId)value;
Store store = luceneOptions.getStore();
Index index = luceneOptions.getIndex();
TermVector termVector = luceneOptions.getTermVector();
Float boost = luceneOptions.getBoost();
//store each property in a unique field
Field field = new Field(name + ".groupId", id.getGroupId() + "", store, index, termVector);
field.setBoost(boost);
document.add(field);
field = new Field(name + ".personId", id.getPersonId() + "", store, index, termVector);
field.setBoost(boost);
document.add(field);
//store the unique string representation in the named field
field = new Field(name,
objectToString(id),
store, index, termVector);
field.setBoost(boost);
document.add(field);
}
Версия поиска в спящем режиме - 4.5.1.Final
Прочитав больше о том, почему это конкретное поведение происходит, я пришел к такому же выводу, как вы, Харди. Я использовал другое решение, передающее список как параметр для фильтра. Но мне больше нравится решение, которое вы предлагаете. Благодаря! – Tvori