【问题标题】:Hibernate Search Tuple QueriesHibernate 搜索元组查询
【发布时间】:2014-12-01 18:57:04
【问题描述】:

我有一个与实体 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();
    }

【问题讨论】:

    标签: hibernate-search


    【解决方案1】:

    你的方法确实行不通。问题是 Lucene 是一个平面数据结构,特别是关联(嵌入式实体)只是“添加”到拥有实体的 Lucene Document 中。在您的情况下,MessageEntity 文档将包含每个 headerKey 分别为 headerValue 的两个字段。一次以“foo”和“bar”为值,56”为值。一次以“123”和“456”为值。不知道其中两个值实际上是一对。

    一个潜在的解决方案是创建一个唯一的字段/值对。使用自定义类桥,您可以创建一个“keyValueField”,其中包含标题键和值作为连接值。然后,在您的查询中,您将使用连接的查询参数定位该字段。

    【讨论】:

      猜你喜欢
      • 2015-01-25
      • 2017-12-16
      • 2014-06-07
      • 2014-11-12
      • 2013-12-02
      • 1970-01-01
      • 1970-01-01
      • 2015-07-17
      • 2012-07-15
      相关资源
      最近更新 更多