2009-11-27 41 views
0

我正在使用Grails的可搜索插件(它爲Compass提供了一個API,它本身是一個通過Lucene的API)。我有一個我希望搜索的Order類,但是,我不想搜索Order的所有實例,只是它們的一個子集。事情是這樣的:使用指南針/ Lucene搜索對象的子集

// This is a Hibernate/GORM call 
List<Order> searchableOrders = Customer.findAllByName("Bob").orders 

// Now search only these orders with the searchable plugin - something like 
searchableOrders.search("name: foo") 

在現實中的關係查詢,以獲得searchableOrders比這更復雜,所以我不能在指南針單獨完成整個查詢(休眠+指南針)。有沒有辦法僅使用Compass/Lucene來搜索特定類的實例的主題。

回答

2

兩個這樣做的方法:

從實現standpoing最簡單的是做所有對象兩個搜索(一個的findAll和搜索),然後找到它們之間的交叉點。如果你緩存findAll調用的結果,那麼你真的需要做一個查詢。

一個更「乾淨」的方式是確保使用Searchable爲域對象的ID編制索引,並且當您獲得findAll結果時,將這些ID傳入搜索查詢,從而限制它。

我不記得了Lucene語法,把我的頭頂部,但你必須這樣做

searchableOrders.search("name: foo AND (ID:4 or ID:5 or ID:8 ...)") 

您可能會遇到在Lucene的查詢大小限制,但我認爲有設置,允許您控制查詢長度。

3

一種方法是使用自定義過濾器。例如,如果你想過濾器的基礎上的ID爲您的域類,則可以將ID添加到搜索的配置領域類:

static searchable = { 
    id name: "id" 
} 

那麼你會編寫自定義過濾器(可去[項目]/src目錄/ JAVA):

import org.apache.lucene.search.Filter; 
import java.util.BitSet; 
import org.apache.lucene.index.TermDocs; 
import org.apache.lucene.index.Term; 
import org.apache.lucene.index.IndexReader; 

import java.io.IOException; 
import java.util.List; 

public class IdFilter extends Filter { 

    private List<String> ids; 

    public IdFilter(List<String> ids) { 
     this.ids = ids; 
    } 

    public BitSet bits(IndexReader reader) throws IOException { 
     BitSet bits = new BitSet(reader.maxDoc()); 
     int[] docs = new int[1]; 
     int[] freqs = new int[1]; 
     for(String id : ids) { 
      if (id != null) { 
       TermDocs termDocs = reader.termDocs(new Term("id", id)); 
       int count = termDocs.read(docs, freqs); 
       if (count == 1) { 
        bits.set(docs[0]); 
       } 
      } 
     } 
     return bits; 
    } 
} 

然後你會把過濾器作爲參數傳遞給您的搜索(確保如果在不同的包的)進口過濾器類:

def theSearchResult = MyDomainClass.search( 
{ 
    must(queryString(params.q))  
}, 
params, 
filter: new IdFilter([ "1" ])) 

在這裏,我只是創建一個硬編碼列表,其中包含單值「1」,但您可以從數據庫,以前的搜索或任何地方檢索ID列表。

你可以很容易地抽象過濾器,我必須在構造函數中使用術語名稱,然後像你想要的那樣傳入「名稱」。