2009-11-19 13 views
6

Şu anda büyük bir veritabanına Lucene.NET tabanlı bir arama gerçekleştirmeye çalışıyorum ve temelde ilişkisel verilerle ilgili bir arama yapmaya çalışan bir taklitle karşılaştım.İlişkisel veri bir Lucene.NET dizininde saklanıyor

Yüksek düzeyde, aramaya çalıştığım veriler gruplanır, her öğe 1 ila 3 gruba aittir. Daha sonra, grupların birleşiminde bulunan tüm öğeler için bir arama yapabilmem gerekir (EG: Her bir öğe hem A grubuna hem de B grubuna aittir).

Bu gruplandırmaların her birinde, aradığım verilerden mevcut olan Kimlikler ve Açıklamalar vardır, ancak açıklamaların alt dizeleri olabilir (EG: "Stuff" adında bir grup ve diğer "Diğer şeyler"), ve aradığımın alt dizesi olan kategorileri eşleştirmek istemiyorum.

Bu filtreleme olmadan verileri geri çekmeyi ve ardından kimlikleri filtrelemeyi düşünüyordum, ancak performans nedeniyle Lucene'den döndürülen verileri sayfalandırmak niyetindeydim. Ayrıca ID'leri alanlara ayırmayı ve alana bir metin araması yapmayı düşündüm, fakat bu bir toplam hack gibi görünüyor ...

Bu tür aramaların nasıl en iyi şekilde kullanılacağına dair herhangi bir fikri olan var mı? Lucene.NET? (Sadece birisi yanlış aracı kullandığımı söylemeden önce açıklığa kavuşturmak için, bu sadece tam metin arama içeren daha geniş bir filtre grubunun bir alt kümesidir. doğru olanı duyun)

cevap

5

İlişkisel veriyi saklamakla ilgili problemlerim vardı Lucene, fakat sahip olduğunuz tek şey düzeltilmesi kolay olmalıydı.

Grup alanlarını belirtiyorsunuz ve bu da alan değerlerinde alt dizeleri aramanızı mümkün kılıyor. Sadece alanı untokenized ekleyin ve beklendiği gibi çalışmalıdır.

aşağıdaki kod küçük bir parça kontrol edin:

internal class Program { 
    private static void Main(string[] args) { 
     var directory = new RAMDirectory(); 
     var writer = new IndexWriter(directory, new StandardAnalyzer()); 
     AddDocument(writer, "group", "stuff", Field.Index.UN_TOKENIZED); 
     AddDocument(writer, "group", "other stuff", Field.Index.UN_TOKENIZED); 
     writer.Close(true); 

     var searcher = new IndexSearcher(directory); 
     Hits hits = searcher.Search(new TermQuery(new Term("group", "stuff"))); 

     for (int i = 0; i < hits.Length(); i++) { 
      Console.WriteLine(hits.Doc(i).GetField("group").StringValue()); 
     } 
    } 

    private static void AddDocument(IndexWriter writer, string name, string value, Field.Index index) { 
     var document = new Document(); 
     document.Add(new Field(name, value, Field.Store.YES, index)); 
     writer.AddDocument(document); 
    } 
} 

örnek untokenized olan endekse iki belgeyi ekler şeyler için bir arama yapar ve bir vuruş yapsın. Kodları değiştirilmiş olarak eklemek için değiştirdiyseniz, şimdi gördüğünüz gibi iki isabetiniz olacaktır.

İlişkisel veriler için Lucene kullanmayla ilgili sorun, joker ve aralık aramalarının her zaman işe yarayacağı beklenebilir. Lucene, bu sorguları çözme yolundan dolayı endeksin büyük olması durumunda durum böyle değildir. cevap için

private static void Main(string[] args) { 
     var directory = new RAMDirectory(); 
     var writer = new IndexWriter(directory, new StandardAnalyzer()); 

     var documentA = new Document(); 
     documentA.Add(new Field("name", "A", Field.Store.YES, Field.Index.UN_TOKENIZED)); 
     documentA.Add(new Field("group", "stuff", Field.Store.YES, Field.Index.UN_TOKENIZED)); 
     documentA.Add(new Field("group", "other stuff", Field.Store.YES, Field.Index.UN_TOKENIZED)); 
     writer.AddDocument(documentA); 
     var documentB = new Document(); 
     documentB.Add(new Field("name", "B", Field.Store.YES, Field.Index.UN_TOKENIZED)); 
     documentB.Add(new Field("group", "stuff", Field.Store.YES, Field.Index.UN_TOKENIZED)); 
     writer.AddDocument(documentB); 
     var documentC = new Document(); 
     documentC.Add(new Field("name", "C", Field.Store.YES, Field.Index.UN_TOKENIZED)); 
     documentC.Add(new Field("group", "other stuff", Field.Store.YES, Field.Index.UN_TOKENIZED)); 
     writer.AddDocument(documentC); 

     writer.Close(true); 

     var query1 = new TermQuery(new Term("group", "stuff")); 
     SearchAndDisplay("First sample", directory, query1); 

     var query2 = new TermQuery(new Term("group", "other stuff")); 
     SearchAndDisplay("Second sample", directory, query2); 

     var query3 = new BooleanQuery(); 
     query3.Add(new TermQuery(new Term("group", "stuff")), BooleanClause.Occur.MUST); 
     query3.Add(new TermQuery(new Term("group", "other stuff")), BooleanClause.Occur.MUST); 
     SearchAndDisplay("Third sample", directory, query3); 
    } 

    private static void SearchAndDisplay(string title, Directory directory, Query query3) { 
     var searcher = new IndexSearcher(directory); 
     Hits hits = searcher.Search(query3); 
     Console.WriteLine(title); 
     for (int i = 0; i < hits.Length(); i++) { 
      Console.WriteLine(hits.Doc(i).GetField("name").StringValue()); 
     } 
    } 
+0

Merhaba HakonB sayesinde:

başka örnek

davranışı göstermek için. Birkaç başka arama için işaretlenmemiş olarak kullandım, ancak sorun, bir öğenin hem "Sayfalar" hem de "Diğer Öğeler" bölümünde yer alabilmesi ve bir ya da her ikisi için arama yapıldığında bulunması gerekir. EG: sadece şeyler şeyler için sadece başka şeyler Ara C {A, B} diğer şeyler için Ara {A, C} malzeme ve diğer şeyler {için Arama içinde malzeme ve diğer şeyler B A A} – fyjham

+0

Doğru sonuçları nasıl alacağınızı gösteren başka bir örnek ekledim - yani şimdi anladım :-) – HakonB

+1

Ah, teşekkürler! Tam olarak peşimdekilere benziyor. Asla, 1 isimle aynı isimde 2 alan ekleyebileceğime hiç rastlanmadı. Hala sanırım tipik bir ilişkisel veritabanı gibi çok fazla düşünüyorum =) – fyjham