我有一个实体Message,它与实体Header有一对多的关系。如何创建基于元组的搜索查询,如
(message.headerKey="foo" and message.headerValue="123") and
(message.headerKey="bar" and message.headerValue="456")
当我在搜索条件中交换标题值时,我当前的逻辑也会匹配
(message.headerKey="foo" and message.headerValue="456") and
(message.headerKey="bar" and message.headerValue="123")
如何使用Hibernate Search API进行基于元组的查询?
这是我的消息实体:
@Entity
@Table(name="MESSAGE")
@Indexed
public class MessageEntity implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="id")
private Long id;
@Column(name="message_timestamp")
private Date timestamp;
@Column(name="payload")
@Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
private String payload;
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, mappedBy = "message")
@IndexedEmbedded
private List<HeaderEntity> headers;
// Getters and Setters
}
这是我的标题实体:
@Entity
@Table(name="HEADER")
public class HeaderEntity implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Column(name="header_key")
@Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
private String headerKey;
@Column(name="header_value")
Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
private String headerValue;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="message_id")
private MessageEntity message;
// Getters and Setters
}
这是我的搜索逻辑:
public List<MessageEntity> search(Header[] headers) {
FullTextEntityManager fullTextEntityManager = org.hibernate.search.jpa.Search.getFullTextEntityManager(mgr);
QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(MessageEntity.class).get();
TermMatchingContext onFieldKey = qb.keyword().onField("headers.headerKey");
TermMatchingContext onFieldValue = qb.keyword().onField("headers.headerValue");
BooleanJunction<BooleanJunction> bool = qb.bool();
org.apache.lucene.search.Query query = null;
for (Header header : headers) {
bool.must(onFieldKey.matching(header.getKey()).createQuery());
bool.must(onFieldValue.matching(header.getValue()).createQuery());
}
query = bool.createQuery();
FullTextQuery persistenceQuery = fullTextEntityManager.createFullTextQuery(query, MessageEntity.class);
persistenceQuery.setMaxResults(10);
return persistenceQuery.getResultList();
}
答案 0 :(得分:0)
你的方法确实不行。问题是Lucene是一个平面数据结构,特别是关联(嵌入实体)只是“添加”到拥有实体的Lucene Document
。在您的情况下,MessageEntity
文档将分别包含headerKey
个headerValue
个字段{{1}}。一次使用“foo”和“bar”作为值,将56“作为值。一次使用”123“和”456“作为值。没有任何概念认为其中两个值实际上是一对。
一种可能的解决方案是创建一个唯一的字段/值对。使用自定义类桥,您可以创建一个“keyValueField”,其中包含标题键和值作为连接值。在查询中,您将使用连接的查询参数来定位此字段。