Reputation: 7255
I am trying to do what seems like a simple search query but am unable to find out if there is a way and if so is it efficient.
I am currently using hibernate with hibernate search 4.3.0. What I am trying to do is to search a specific collection. For example I have an Inventory class that contains a List of InventoryItem. I would like to perform a keyword search where only the items in a specific inventory are searched. Is it possible to limit the search to a specific. Both the Inventory and InventoryItem class extends DatastoreObject which has a @Id Long id field as it's primary key.
/**
* Inventory is a container of inventory objects.
*
* @author chinshaw
*/
@Entity
@Indexed
public class Inventory extends DatastoreObject {
@Size(min = 5, max = 256, message = "inventory name must be between 5 and 256 characters")
@Column(length = 256)
@Field
private String name;
@Size(max = 512, message = "inventory description cannot exceed 512 characters")
@Column(length = 512)
@Field
private String description;
/**
* List of all inventory items in this object.
*/
@IndexedEmbedded
@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
private List<InventoryItem> inventoryItems = new ArrayList<InventoryItem>();
...
/**
*
* @author chinshaw
*/
@Entity
@Indexed
public class InventoryItem extends DatastoreObject implements IHasImage {
/**
* String manufacturer's serial number.
*/
private String sin;
/**
* This is the name of the item.
*/
@NotNull
@Field
private String name;
/**
* This is the text description of the object.
*/
@Size(max = 200, message = "description must be less than 200 characters")
@Field
private String description;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "inventory_id")
private Inventory inventory;
...
public List<InventoryItem> searchItems(Long inventoryId, String searchContext) {
FullTextEntityManager session = Search.getFullTextEntityManager(getEntityManager());
EntityTransaction tx = session.getTransaction();
QueryBuilder qb = session.getSearchFactory().buildQueryBuilder().forEntity(InventoryItem.class).get();
// How do I limit the search to only contain the inventoryId.
org.apache.lucene.search.Query searchQuery = qb.keyword().onFields("title", "description").matching(searchContext).createQuery();
javax.persistence.Query query = session.createFullTextQuery(searchQuery, InventoryItem.class);
// execute search
List<InventoryItem> items = query.getResultList();
tx.commit();
return items;
}
Upvotes: 0
Views: 375
Reputation: 734
You should be able to do this with the bool() method on QueryBuilder. For instance, to filter the returned InventoryItem
s such that they must belong to the Inventory
with ID inventoryId
, you can use:
org.apache.lucene.search.Query searchQuery = qb.bool()
.must(qb.keyword().onFields("title", "description").matching(searchContext).createQuery())
.must(qb.keyword().onField("inventory.id").matching(inventoryId).createQuery())
.createQuery();
This will create an AND condition between your search on the title/description of the InventoryItem
s and the ID of the Inventory
you want matched.
Note, however, that you must annotate InventoryItem.inventory
as @IndexedEmbedded
for it to be included in InventoryItem
's index.
Upvotes: 2