当前位置: 首页 > 知识库问答 >
问题:

lucene/hibernate搜索-不能按集合中子类中的字段搜索

冀啸
2023-03-14

我有:一个request实体有一个stage的集合,每个阶段都有一个stageitem集合。Stage项可以有几种类型,我在JPA/Hibernatesingle_table中使用它们作为带有鉴别器列的继承策略。

我需要lucene查询返回在类型a的阶段项(类stageitema中的字段adetail)中具有特定细节的请求。我无法让hibernate搜索查看子类stageitema中的字段adetail

因此这个lucene查询不起作用(返回0个结果):

stages.stageItems.aDetail:blah

但基于StageItem中的字段进行搜索有效:

stages.stageItems.comment:yuppie
@Entity
@Table(name = "REQUEST")
@Indexed(index = "RequestIndex")
class Request implements Serializable {
    //...
    @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
    @MapKeyColumn(name = "type", length = 50, nullable = false)
    @JoinTable(
            name = "REQUEST_STAGE",
            joinColumns = @JoinColumn(name = "REQUEST_ID", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "STAGE_ID", referencedColumnName = "id")
    )
    @IndexedEmbedded
    private Map<String, Stage> stages = new HashMap<>();
    //...
}

@Entity
@Table(name = "STAGE")
public class Stage implements Serializable {
    //...
    @OneToMany(fetch = FetchType.EAGER, targetEntity = StageItem.class, cascade = {
            CascadeType.ALL,
    }, orphanRemoval = true)
    @JoinTable(
            name = "STAGE_TO_STAGE_ITEM",
            joinColumns = @JoinColumn(name = "STAGE_ID"),
            inverseJoinColumns = @JoinColumn(name = "STAGE_ITEM_ID")
    )
    @Fetch(FetchMode.JOIN)
    @IndexedEmbedded
    private Set<StageItem> stageItems = new HashSet<>();
    //...
}

@Entity
@Table(name = "STAGE_ITEM")
@DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class StageItem implements Serializable {
    //...
    @Column(name = "TYPE")
    @Field
    protected String type;

    @Column(name="COMMENT")
    @Field
    protected String comment;
    //...
}

@Entity
@DiscriminatorValue(value = "A")
public class StageItemA extends StageItem {
    //...
    @Column(name="A_DETAIL")
    @Field
    private String aDetail;
    //...
}

共有1个答案

赏彭薄
2023-03-14

@indexedembedded只考虑属性的声明类型,而不考虑运行时类型。因此,使用当前的映射,@indexedembedded将只索引类stageitem中声明的字段,而不是stageitema中声明的字段。

有计划改变这种情况,并考虑运行时多态性,但我们还没有完全做到这一点:它并不像看起来那么明显,因为我们需要检测多个子类之间索引模式中的冲突。请参阅HSEARCH-438以跟踪进度并查找更多信息。

同时,最简单的方法是在stageitem中声明返回null的方法和字段,并在stageitema中重写它以返回正确的值。

类似这样的事情:


@Entity
@Table(name = "STAGE_ITEM")
@DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class StageItem implements Serializable {
    //...
    @Column(name = "TYPE")
    @Field
    protected String type;

    @Column(name="COMMENT")
    @Field
    protected String comment;
    //...

    @Field(name = "aDetail")
    @javax.persistence.Transient
    protected String getADetailForHibernateSearch() {
        return null;
    }
}

@Entity
@DiscriminatorValue(value = "A")
public class StageItemA extends StageItem {
    //...
    @Column(name="A_DETAIL")
    private String aDetail;
    //...

    @Override
    protected String getADetailForHibernateSearch() {
        return aDetail;
    }
}

主要的缺点是索引一个瞬态方法会对性能产生负面影响:简而言之,由于Hibernate Search不知道数据来自何处,它会认为对StageItem的任何属性的任何更改都需要重新索引,而以前只有当相关属性被修改时,它才会触发重新索引。您可以尝试一下,但在您的情况下,性能可能不会那么差。

 类似资料:
  • 我在我的应用程序中使用Hibernate搜索。其中一个子集合映射为IndexeDemBedded。子对象有两个字段,一个是id,另一个是date(使用date resoultion到毫秒)。当我搜索ID=1(或某个值)并且date等于另一个值时,我会得到第一个和第二个匹配的所有情况的结果。我只想在同一个孩子中获得两个字段匹配的记录,但我在不同的孩子中获得匹配,结果会高得多。下面是代码片段 主类是用

  • 我正在使用Hibernate Search/Lucene Intégration开发一个J2E应用程序。我索引文档(和其他实体),并希望对其进行不区分重音的搜索(内容和类的字段)。 这样做好吗?是否没有param或conf属性让FrenchAnalyzer忽略重音? 谢谢

  • 在测试此文本时,我在要在文本中搜索的列上创建了lucene(3.0.1)索引: 如果我按关键字搜索,它会给出结果,但按 我正在使用standardAnalyzer: 因为已设置,它应创建令牌,并且应存在$GLD。Analyzer将从文本中删除停止字,因为word也将在该过程中删除。

  • 我使用Mongodb和我的数据库模式,如下所示: 我要找到所有的记录,名字+名字喜欢‘瓦希德kh’。在SQL中,这将是: 从firstName+lastName类似“%Vahid KH%”的表中选择*

  • 我刚开始使用hibernate lucene搜索。从几天以来,我一直致力于搜索关键字与特殊字符。我正在使用MultiFieldQueryParser进行精确短语匹配以及布尔搜索。但在这个过程中,我无法得到搜索关键字的结果,如“有1年以上的经验”,如果我没有在搜索关键字周围添加任何引号,那么我就得到了结果。所以我在执行lucene查询时观察到的是,它正在转义特殊符号(+)。我正在使用Standard