-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 
Author Message
 Post subject: Searching collections with Lucene
PostPosted: Sun Jun 01, 2008 9:38 am 
Newbie

Joined: Sun Jun 01, 2008 7:03 am
Posts: 3
Hi folks, i encountered a problem while trying to query a Lucene Index using Hibernate Search. (This is a stock JBOSS-4.2.2.GA build with integrated Hibernate/Lucene)

Use case:

Entities:
Code:
@Entity
@Name("job")
@Table(name = "job", schema = "public")
@Indexed
public class Stelle implements java.io.Serializable {

        Long id;

   @IndexedEmbedded(depth=3)
   private Firm firm;

   @Field(index=Index.UN_TOKENIZED)
   @FieldBridge(impl = BooleanBridge.class)
   private Boolean aktuell;

   @ContainedIn
   private Person person;

   @Id
   @GeneratedValue(strategy = SEQUENCE, generator = "generator")
   @Column(name = "id", unique = true, nullable = false)
   @DocumentId
   public Long getId() {
      return this.id;
   }

   public void setId(Long id) {
      this.id = id;
   }

   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "firm_id")
   public Firma getFirm() {
      return this.firm;
   }

   public void setFirm(Firm firm) {
      this.firm = firm;
   }

   @Column(name = "current", length = 1)
   public Boolean getCurrent() {
      return current;
   }

   public void setAktuell(Boolean current) {
      this.current = current;
   }

   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "person_id")
   public Person getPerson() {
      return this.person;
   }

   public void setPerson(Person person) {
      this.person = person;
   }
}

@Entity
@Table(name = "firm", schema = "public")
@Embeddable
@Name("firm")
public class Firm implements java.io.Serializable {

   private Long id;

   @Fields( { @Field(index = Index.TOKENIZED),
         @Field(name = "ufirmname", index = Index.UN_TOKENIZED) })
   private String firmname;

   @ContainedIn
   private Collection<Job> jobs = new ArrayList<Job>();

   @Id
   @GeneratedValue(strategy = SEQUENCE, generator = "generator")
   @Column(name = "id", unique = true, nullable = false)
   @DocumentId
   public Long getId() {
      return this.id;
   }

   public void setId(Long id) {
      this.id = id;
   }

   @Column(name = "firmname", length = 50)
   public String getFirmname() {
      return firmname;
   }

   public void setFirmname(String firmname) {
      this.firmname = firmname;
   }

   @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE,
         CascadeType.REFRESH }, fetch = FetchType.LAZY, mappedBy = "firm")
   public Collection<Job> getJobs() {
      return this.jobs;
   }

   public void setStelles(Collection<Job> jobs) {
      this.jobs = jobs;
   }
}

@Entity
@Name("person")
@Table(name = "person", schema = "public")
@Indexed
public class Person implements java.io.Serializable {

   private Long id;

   @IndexedEmbedded(depth = 4)
   private Collection<Job> jobs = new ArrayList<Job>();

   @Id
   @GeneratedValue(strategy = SEQUENCE, generator = "generator")
   @Column(name = "id", unique = true, nullable = false)
   @DocumentId
   public Long getId() {
      return this.id;
   }

   public void setId(Long id) {
      this.id = id;
   }

   @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE,
         CascadeType.REFRESH, CascadeType.REMOVE }, fetch = FetchType.LAZY, mappedBy = "person")
   @OrderBy("current")
   public Collection<Job> getJobs() {
      return this.Jobs;
   }

   public void setJobs(Collection<Job> jobs) {
      this.stelles = stelles;
   }
}

Query trying to find person objects:
Code:
+jobs.firm.firmname:siemens* +jobs.current:true


This returns all person objects belonging to siemens* (intended), but also everbody who had a affiliation with siemens* in the past (job.aktuell == false, not intended). I reconstructed the index using Luke and this is what it stores for jobs.aktuell (example with one person having three jobs in the collection):
false false true
To me it seems like Hibernate concatenates all collection values and Lucene assumes a successful match if at least one match (job.aktuell == true) is found in the entire collection.

Is this intended behaviour and why? How do i search the collection in the way i outlined above, i.e. "get all persons who have job.aktuell == true and for this job firm.firmname == siemens*"?


Top
 Profile  
 
 Post subject: Re: Searching collections with Lucene
PostPosted: Mon Jun 02, 2008 10:10 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
Hi,

mabi wrote:
Is this intended behaviour and why?

Yes, the behavior is intended. In your example you are searching the Person index. There is one Lucene document for each person. Remember that a Lucene document is nothing else like a set of key/value pairs (a map if you like). You configured the job collection to be indexed embedded that means for each instance in the jobs collection the configured key/value pairs get added (always using the same field name). In your example the field aktuell gets added three times. The Lucene document has no concept of 'grouping' a set of fields together. When searching all fields are treated the same.

mabi wrote:
How do i search the collection in the way i outlined above, i.e. "get all persons who have job.aktuell == true and for this job firm.firmname == siemens*"?

One way would be to actually search the Job index and specify aktuell == true.

--Hardy


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 02, 2008 8:26 pm 
Newbie

Joined: Sun Jun 01, 2008 7:03 am
Posts: 3
Thanks, that was most helpful. I'll try to integrate that with our software.


Top
 Profile  
 
 Post subject: Re: Searching collections with Lucene
PostPosted: Tue Sep 09, 2008 3:34 am 
Newbie

Joined: Thu Sep 13, 2007 7:01 am
Posts: 11
hardy.ferentschik wrote:
Hi,

mabi wrote:
Is this intended behaviour and why?

Yes, the behavior is intended. In your example you are searching the Person index. There is one Lucene document for each person. Remember that a Lucene document is nothing else like a set of key/value pairs (a map if you like). You configured the job collection to be indexed embedded that means for each instance in the jobs collection the configured key/value pairs get added (always using the same field name). In your example the field aktuell gets added three times. The Lucene document has no concept of 'grouping' a set of fields together. When searching all fields are treated the same.

mabi wrote:
How do i search the collection in the way i outlined above, i.e. "get all persons who have job.aktuell == true and for this job firm.firmname == siemens*"?

One way would be to actually search the Job index and specify aktuell == true.

--Hardy


Hi,

I am facing the same problem when searching collections with Hibernate Search. I want to search a collection of contacts on a person object.

My search query is like: "+person.contacts.owner:testuser +person.contacts.date:2006*"

What I want is to find all persons having contacts with testuser and _these_ contacts should be in 2006.
Now I get all persons having contacts with testuser and having _other_ contacts in 2006.

@Hardy: Your suggestion would by in my case to search the contacts index.. Could you give me a hint, on how to do that and get person objects back? As far as I know I would get contact objects back as results. I need person objects...

Would there be any other possibility to archive what I want?

Thanks!

Alexander


Top
 Profile  
 
 Post subject: Re: Searching collections with Lucene
PostPosted: Sat Sep 13, 2008 2:08 pm 
Newbie

Joined: Thu Sep 11, 2008 2:55 pm
Posts: 6
brachie wrote:
@Hardy: Your suggestion would by in my case to search the contacts index.. Could you give me a hint, on how to do that and get person objects back? As far as I know I would get contact objects back as results. I need person objects...


I would also be interested in that hint.

Thanks
Johannes


Top
 Profile  
 
 Post subject:
PostPosted: Sat Sep 13, 2008 4:02 pm 
Newbie

Joined: Thu Sep 13, 2007 7:01 am
Posts: 11
Hi,

well I figured it out for myself. The basic idea is as follows:

I am searching the contacts index. What I get back is a list of matching contacts. To get back the persons instead, I iterate through the returned contact list and call contact.getPerson() on every contact and add the person to another list which is what I want basically.

Since the performance is not very good, with this approach (loading every person from the database for every matching contact is heavy), I decided to make a projection on the personId which is part of my contact index. So I do not need to ask the database for every person.

Regards,

Alexander


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 15, 2008 11:09 pm 
Newbie

Joined: Sat Jul 01, 2006 9:38 pm
Posts: 17
brachie wrote:
Hi,

well I figured it out for myself. The basic idea is as follows:

I am searching the contacts index. What I get back is a list of matching contacts. To get back the persons instead, I iterate through the returned contact list and call contact.getPerson() on every contact and add the person to another list which is what I want basically.

Since the performance is not very good, with this approach (loading every person from the database for every matching contact is heavy), I decided to make a projection on the personId which is part of my contact index. So I do not need to ask the database for every person.

Regards,

Alexander


Hi, Alexander.
I want to know how you treat the paging problem.
Thanks.

--suyejun.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 16, 2008 8:06 am 
Newbie

Joined: Thu Sep 13, 2007 7:01 am
Posts: 11
@suyejun: Well, in my use-case I return a maximum of 50 results. So pagination in big result-sets is not neccessary for me.

But generally you can use methods like setFirstResult() and setMaxResult() on a FulltextQuery. Have a look at the Hibernate-Search docs: http://www.hibernate.org/hib_docs/search/reference/en/html/search-query.html#d0e1846

Regards,

Alexander


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 16, 2008 8:09 am 
Newbie

Joined: Thu Sep 11, 2008 2:55 pm
Posts: 6
brachie wrote:
I am searching the contacts index. What I get back is a list of matching contacts. To get back the persons instead, I iterate through the returned contact list and call contact.getPerson() on every contact and add the person to another list which is what I want basically.


Wouldn't it be a good idea to store the ID of each Person in the Contact index itself and then use projection to get the Person-IDs needed for the Hibernate-Query that returns the desired Person-Instances?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 16, 2008 8:39 am 
Newbie

Joined: Thu Sep 13, 2007 7:01 am
Posts: 11
languitar wrote:
brachie wrote:
I am searching the contacts index. What I get back is a list of matching contacts. To get back the persons instead, I iterate through the returned contact list and call contact.getPerson() on every contact and add the person to another list which is what I want basically.


Wouldn't it be a good idea to store the ID of each Person in the Contact index itself and then use projection to get the Person-IDs needed for the Hibernate-Query that returns the desired Person-Instances?


Correct. Please read the second part of my post above! ;)

Alexander


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 16, 2008 8:46 am 
Newbie

Joined: Thu Sep 11, 2008 2:55 pm
Posts: 6
brachie wrote:
Correct. Please read the second part of my post above! ;)


Oops ;)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 16, 2008 10:06 am 
Newbie

Joined: Sat Jul 01, 2006 9:38 pm
Posts: 17
brachie wrote:
@suyejun: Well, in my use-case I return a maximum of 50 results. So pagination in big result-sets is not neccessary for me.

But generally you can use methods like setFirstResult() and setMaxResult() on a FulltextQuery. Have a look at the Hibernate-Search docs: http://www.hibernate.org/hib_docs/search/reference/en/html/search-query.html#d0e1846

Regards,

Alexander


Hi, Alexander.
Thank you for your reply.
Suppose a collection instead of an object, just like one person has some contacts, I think your method will have some pagination problem.

Regards,

--suyejun


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.