如何使用hibernate的lucene搜索进行投影 [英] How to use projections with hibernate lucene search

查看:85
本文介绍了如何使用hibernate的lucene搜索进行投影的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做hibernate的lucene搜索,它在获取整个域对象时工作得很好。但是我的要求是预测。它只在OneToMany相关字段上获得单值。所以我怎样才能获得带有投影的@IndexedEmbedded字段的所有值。请协助您的建议。
以下片段是我的代码

$ p $ @Indexed(index =Skills)
@AnalyzerDef( name =skillAnalyzer,
tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class),
filters = {
@TokenFilterDef(factory = LowerCaseFilterFactory.class),
@TokenFilterDef工厂= SnowballPorterFilterFactory.class,params = {
@Parameter(name =language,value =English)
})
})
@实体
@Table(name =skills)
public class技能{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name =skill_id)
@Field(name =skillIdPk,index = Index.YES,analyze = Analyze.YES,store = Store.YES)
private int skillId;

@Field(index = Index.YES,analyze = Analyze.YES,store = Store.YES)
@Column(name =skill)
private String skill;

@Column(name =skill_type)
private String skillType =default;

// setters& getters


$ b @Indexed(index =JobSeeker)
@AnalyzerDef(name =jobSeekerAnalyzer,tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class ),filters = {
@TokenFilterDef(factory = LowerCaseFilterFactory.class),
@TokenFilterDef(factory = SnowballPorterFilterFactory.class,params = {
@Parameter(name =language,value = English)})})
@Entity
@Table(name =jobseeker)
@Component
public class JobSeeker {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name =jobseeker_id)
private long jobSeekerId;

@Column(name =email_id,unique = true)
private String emailId;

@Column(name =first_name)
private String firstName;

@Column(name =middle_name)
private String middleName;

@Column(name =last_name)
private String lastName;

@Column(name =password)
private String password;


@IndexedEmbedded
私人设置< JobSeekerSkills> jobSeekerSkills = new HashSet< JobSeekerSkills>();
// setters& getters


}


@Indexed(index =JobSeekerSkills)
@AnalyzerDef(name =jobseekerSkillAnalyzer,
tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class),
filters = {
@TokenFilterDef(factory = LowerCaseFilterFactory.class),
@TokenFilterDef(factory = SnowballPorterFilterFactory.class,params = {
@Parameter(name =language,value =English)
})
})
@Entity
@Table(name =jobseeker_skills )

public class JobSeekerSkills
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name =jobseeker_skill_id)
私人长期求职SeekerSkillId;

@ManyToOne
@JoinColumn(name =jobseeker_jobseeker_id)
私人JobSeeker jobSeeker;

@ManyToOne
@JoinColumn(name =skills_skill_id)
@IndexedEmbedded
私人技能;


// setters&获得者

}

// ============================== =========================================
//这是我的Dao代码
FullTextSession fullTextSession = Search.getFullTextSession(session);
fullTextSession.createIndexer()。startAndWait();
QueryBuilder qb = fullTextSession.getSearchFactory()。buildQueryBuilder()。forEntity(JobSeeker.class).get();
查询查询=空;
for(String string:skills){
query = qb.keyword()。onField(jobSeekerSkills.skills.skillIdPk)。matching(Integer.parseInt(string))。createQuery();
}
org.hibernate.search.FullTextQuery query1 =
fullTextSession.createFullTextQuery(query,JobSeeker.class);
query1.setProjection(jobSeekerId,jobSeekerSkills.skills.skill);
列出结果= query1.list();
for(int i = 0; i< results.size(); i ++){
Object [] object =(Object [])results.get(i);
System.out.println(object [0]);
System.out.println(object [1]);
}
//列表<技能> authorName1 =(List<技能>)firstResult [1];
// System.out.println(authorName1);
返回结果;


解决方案

正如 Hibernate Search文档


投影不适用于通过@IndexedEmbedded索引的集合或地图

在你的情况下,试图在 jobSeekerSkills.skills.skill 上进行投影,其中 jobSeekerSkills 是通过<$ c索引的集合$ c> @IndexedEmbedded ,不是一个好主意。



我想指出的是,由于您只是执行关键字在数值字段上查询,你最好使用Hibernate ORM做一个经典的JQPL / SQL查询。



无论如何, >真的想要使用Hibernate Search,从你的查询来看,你不需要在集合上进行投影。相反,只需将 @IndexedEmbedded(includePaths =includePaths)添加到 jobSeeker 属性中> JobSeekerSkills ,然后重新将您的查询重新定位到实体 JobSeekerSkills 的索引:

  FullTextSession fullTextSession = Search.getFullTextSession(session); 
fullTextSession.createIndexer()。startAndWait();
QueryBuilder qb = fullTextSession.getSearchFactory()。buildQueryBuilder()。forEntity(JobSeeker.class).get();
查询查询=空;
for(String string:skills){
query = qb.keyword()。onField(skills.skillIdPk)。matching(Integer.parseInt(string))。createQuery();
}
org.hibernate.search.FullTextQuery query1 =
fullTextSession.createFullTextQuery(query,JobSeeker.class);
query1.setProjection(jobSeeker.jobSeekerId,skills.skill);
列出结果= query1.list();
for(int i = 0; i< results.size(); i ++){
Object [] object =(Object [])results.get(i);
System.out.println(object [0]);
System.out.println(object [1]);
}
//列表<技能> authorName1 =(List<技能>)firstResult [1];
// System.out.println(authorName1);
返回结果;

注意: includePaths code> @IndexedEmbedded 只是必要的,因为您已经在关联的反面( @IndexedEmbedded > JobSeeker.jobSeekerSkills );它避免了无限递归(JobSeeker.jobSeekerSkills.jobSeeker.jobSeekerSkills.jobSeeker.jobSeekerSkills ...)。如果您删除 JobSeeker.jobSeekerSkills 上的 @IndexedEmbedded ,则还可以删除 includePaths 对新的 @IndexedEmbedded


I am doing hibernate lucene search .It is working fine with getting entire domain object.But my requirement is projections.It only getting single value on OneToMany associated fields.So how can I get all values of @IndexedEmbedded fields with projections.Please assists your suggestions. The following snippet is my code

    @Indexed(index="Skills")
                @AnalyzerDef(name = "skillAnalyzer",
                tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class),
                filters = {
                  @TokenFilterDef(factory = LowerCaseFilterFactory.class),
                  @TokenFilterDef(factory = SnowballPorterFilterFactory.class, params = {
                    @Parameter(name = "language", value = "English")
                  })
                })
                @Entity
                @Table(name = "skills")
                public class Skills {
                    @Id
                    @GeneratedValue(strategy = GenerationType.AUTO)
                    @Column(name = "skill_id")
                    @Field(name="skillIdPk",index=Index.YES, analyze=Analyze.YES, store=Store.YES)
                    private int skillId;

                    @Field(index=Index.YES, analyze=Analyze.YES, store=Store.YES)
                    @Column(name = "skill")
                    private String skill;

                    @Column(name = "skill_type")
                    private String skillType = "default";

                    //setters & getters
                }


            @Indexed(index = "JobSeeker")
            @AnalyzerDef(name = "jobSeekerAnalyzer", tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class), filters = {
                    @TokenFilterDef(factory = LowerCaseFilterFactory.class),
                    @TokenFilterDef(factory = SnowballPorterFilterFactory.class, params = {
                            @Parameter(name = "language", value = "English") }) })
            @Entity
            @Table(name = "jobseeker")
            @Component
            public class JobSeeker {
                @Id
                @GeneratedValue(strategy = GenerationType.AUTO)
                @Column(name = "jobseeker_id")
                private long jobSeekerId;

                @Column(name = "email_id", unique = true)
                private String emailId;

                @Column(name = "first_name")
                private String firstName;

                @Column(name = "middle_name")
                private String middleName;

                @Column(name = "last_name")
                private String lastName;

                @Column(name = "password")
                private String password;


                @IndexedEmbedded
                private Set<JobSeekerSkills> jobSeekerSkills = new HashSet<JobSeekerSkills>();
            //setters & getters


            }


        @Indexed(index="JobSeekerSkills")
        @AnalyzerDef(name = "jobseekerSkillAnalyzer",
        tokenizer = @TokenizerDef(factory=StandardTokenizerFactory.class),
        filters = {
          @TokenFilterDef(factory = LowerCaseFilterFactory.class),
          @TokenFilterDef(factory = SnowballPorterFilterFactory.class, params = {
            @Parameter(name = "language", value = "English")
          })
        })
        @Entity
        @Table(name="jobseeker_skills")

        public class JobSeekerSkills 
        {
            @Id
            @GeneratedValue(strategy=GenerationType.AUTO)
            @Column(name="jobseeker_skill_id")
            private long jobSeekerSkillId;

            @ManyToOne
            @JoinColumn(name="jobseeker_jobseeker_id")
            private JobSeeker jobSeeker;

            @ManyToOne
            @JoinColumn(name="skills_skill_id")
            @IndexedEmbedded
                private Skills skills;


        //setters & getters

        }

//=======================================================================
//This is my Dao code
FullTextSession fullTextSession = Search.getFullTextSession(session);
        fullTextSession.createIndexer().startAndWait();
        QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(JobSeeker.class).get();
        Query query = null;
        for (String string : skills) {
            query = qb.keyword().onField("jobSeekerSkills.skills.skillIdPk").matching(Integer.parseInt(string)).createQuery();
        }
        org.hibernate.search.FullTextQuery query1 =
                fullTextSession.createFullTextQuery(query, JobSeeker.class);
            query1.setProjection("jobSeekerId", "jobSeekerSkills.skills.skill");
            List results = query1.list();
            for (int i = 0; i < results.size(); i++) {
                Object[] object = (Object[]) results.get(i);
                System.out.println(object[0]);
                System.out.println(object[1]);
            }
        //  List<Skills> authorName1 = (List<Skills>) firstResult[1];
        //  System.out.println(authorName1);
        return results;

解决方案

As mentioned in the Hibernate Search documentation:

projection does not work on collections or maps which are indexed via @IndexedEmbedded

So in your case, trying to project on jobSeekerSkills.skills.skill, with jobSeekerSkills being a collection indexed via @IndexedEmbedded, is not a good idea.

I'd like to point out that, since you're only performing a keyword query on a numeric field, you'd probably be better off just doing a classic JQPL/SQL query using Hibernate ORM.

Anyway, if for whatever reason you really want to use Hibernate Search for this, judging from your query, you don't need to project on a collection. Instead, just add an @IndexedEmbedded(includePaths = "includePaths") to the jobSeeker property of JobSeekerSkills, and then rework your query to target the index for entity JobSeekerSkills:

    FullTextSession fullTextSession = Search.getFullTextSession(session);
    fullTextSession.createIndexer().startAndWait();
    QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(JobSeeker.class).get();
    Query query = null;
    for (String string : skills) {
        query = qb.keyword().onField("skills.skillIdPk").matching(Integer.parseInt(string)).createQuery();
    }
    org.hibernate.search.FullTextQuery query1 =
            fullTextSession.createFullTextQuery(query, JobSeeker.class);
        query1.setProjection("jobSeeker.jobSeekerId", "skills.skill");
        List results = query1.list();
        for (int i = 0; i < results.size(); i++) {
            Object[] object = (Object[]) results.get(i);
            System.out.println(object[0]);
            System.out.println(object[1]);
        }
    //  List<Skills> authorName1 = (List<Skills>) firstResult[1];
    //  System.out.println(authorName1);
    return results;

Note: the includePaths on the new @IndexedEmbedded is only necessary because you already have an @IndexedEmbedded on the reverse side of the association (JobSeeker.jobSeekerSkills); it avoids infinite recursion (JobSeeker.jobSeekerSkills.jobSeeker.jobSeekerSkills.jobSeeker.jobSeekerSkills...). If you remove the @IndexedEmbedded on JobSeeker.jobSeekerSkills, then you can also remove the includePaths on the new @IndexedEmbedded.

这篇关于如何使用hibernate的lucene搜索进行投影的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆