The LINQ to Lucene project takes its approach from LINQ to SQL. There is an Index<T> that provides access to types that are propertly decorated with Document and Field attributes and the implement that marker interface IIndexable using both Standard and Custom Query Operators.

To manage a set of indexes, LINQ to Lucene has an IndexSet. Also, LINQ to SQL data layers can be used as a source for an index set with DatabaseIndexSet<TDataContext>.

Query operators work on both the string-properties and the class itself if it implements IIndex. When the left-operand is a property, field-notation syntax is used. When the left-operand is the class itself, the default fields are used (as defined by the FieldAttribute decorations of the class). The exception to this rule is the Search method provided only by the class itself, which accepts inline native lucene query syntax. Additional methods for the right operands are Boost) and Required.

Type-Conversion occurs using .Net Type-Converters. The property of any type will be converted from the Lucene Index's string type to the appropriate type used by the property as long its type uses a type converter that supports conversion from a string. This automatically includes many .net types including string, int, bool, datetime and more.

Query Reference
The table below is based off of the Lucene Syntax Reference
Lucene SyntaxLINQ to Lucene
Terms & Phrases"test" or "hello dolly"c.Match("test") or c.Match("hello dolly")
Fieldstitle:"The Right way" and text:goc.Title == "The Right way" or c.Text == "go"
WildCardamb?rc.ContactName.Match("amb?r")
Prefixamber*c.ContactName.StartsWith("amber")
Fuzzyroam~ or roam~0.8c.ContactName.Like("roam") or c.ContactName.Like("roam", 0.8)
Proximity"jakarta apache"~10c.ContactName.Like("jakarta apache", 10)
Inclusive Rangemod_date:[20020101 TO 20030101]c.ModifiedDate.Includes("20020101", "20030101")
Exclusive Rangetitle:{Aida TO Carmen}c.Title.Between("Aida", "Carmen")
Boostingjakarta^4 apachec.Title.Match("jakarta".Boost(4), apache)
Boolean Or"jakarta apache" OR jakartawhere c.Match("jakarta apache") || c.Match("jakarta")
Boolean And"jakarta apache" AND "Apache Lucene"where c.Match("jakarta apache") && c.Match("Apache Lucene")
Boolean Not"jakarta apache" NOT "Apache Lucene"where c.Match("jakarta apache") && !c.Match("Apache Lucene")
Required+jakarta lucenec.Title.Match("jakarta".Require(), "lucene")
Grouping(jakarta OR apache) AND websitewhere (c.Title == "jakarta" || c.Title == "apache") && (c.Title == "website")
Native Syntaxie. title:{+return +"pink panther")c.Search("title:(return +\"pink panther\"")


Code Samples Simple Query
// Output: (ContactName:maria)
var query = from c in context.Customers
            where c.ContactName == "maria"
            select c;

Query with Variables and Projection
// Output: (ContactName:Maria)
string name = "Maria";
var query = from c in context.Customers
            where c.ContactName == name
            select new { Name=c.ContactName, Id=c.CustomerID, Company=c.CompanyName };

And, Or, Grouping Queries
// Output: ((ContactName:maria) OR (CompanyName:"Ernst Handel"))
var query = from c in context.Customers
            where (c.ContactName == "maria") || (c.CompanyName == "Ernst Handel")
            select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

// Output: ((ContactName:maria) AND (CompanyName:"Alfreds Futterkiste"))
var query = from c in context.Customers
            where (c.ContactName == "maria") && (c.CompanyName == "Alfreds Futterkiste")
            select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

// Output: ((ContactName:maria) OR ((ContactName:"Aria Cruz") AND ("Familia Arquibaldo"))
var query = from c in context.Customers
            where (c.ContactName == "maria") || (c.ContactName == "Aria Cruz" && c.CompanyName == "Familia Arquibaldo")
            select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

Default Field Query
// Output: Folies
var query = from c in context.Customers
             where (c.Match("Folies"))
             select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

WildCard & Prefix Queries
// Output: (ContactName:ma?ia)
var query = from c in context.Customers
            where c.ContactName == "ma?ia"
            select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

// Output: ContactName:(mar*)
var query = from c in context.Customers
            where c.ContactName.StartsWith("mar")
            select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

// Output: ContactName:(Maria And*)
var query = from c in context.Customers
            where c.ContactName.StartsWith("Maria And")
            select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

Range Queries
// Output: ContactName:{Annette TO Aria}
var query = from c in context.Customers
            where c.ContactName.Between("Annette", "Aria")
            select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

// Output: ContactName:[Annette TO Aria]
var query = from c in context.Customers
            where c.ContactName.Include("Annette", "Aria")
            select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

Fuzzy & Proximity Queries
// Output: ContactName:Maria~
var query = from c in context.Customers
            where c.ContactName.Like("Maria")
            select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

// Output: ContactName:"Maria An"~1
var query = from c in context.Customers
            where c.ContactName.Like("Maria An", 1)
            select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

Require & Boost Queries
// Output: ContactName:(+maria Anders)
var query = from c in context.Customers
            where c.ContactName.Match("maria".Require(), "Anders")
            select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

// Output: ContactName:(maria^3 Art)
var query = from c in context.Customers
            where c.ContactName.Match("maria".Boost(3), "Art")
            select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

Native Syntax Query
// Output: ((+la^4 OR en) OR (WeirdCustomName:mar* AND !CompanyName:Victuailles))
var query = from c in context.Customers
            where c.Search("((+la^4 OR en) OR (WeirdCustomName:mar* AND !CompanyName:Victuailles))")
            select new { Name = c.ContactName, Id = c.CustomerID, Company = c.CompanyName };

Credit
The Wayward Weblog
Again, credit must be given to Matt Warren of the Wayward Weblog who provided the building blocks used by LINQ to Lucene with regards to the Expression Tree Evaluation and projection. For a deeper understanding of how this project was implemented, it is reccomended that you spend time with the LINQ series he provides. Thank you Matt.

Last edited Jul 22, 2008 at 9:11 AM by CVertex, version 32

Comments

No comments yet.