chriseldredge / Lucene.Net.Linq

LINQ provider to run native queries on a Lucene.Net index
Other
151 stars 66 forks source link

Query multiple fields all at once #66

Closed mahara closed 10 years ago

mahara commented 10 years ago

Hi,

Consider the following model:

public class MediaItem
{
    public string Title { get; set; }
    public string Album { get; set; }
    public string Artist { get; set; }
    public string AlbumArtist { get; set; }
    public string Genre { get; set; }
}

I'd like to know how I could possibly query multiple fields using the following query text:

    var searchQuery = "wonderland album:sky artist:alice genre:pop";

with "wonderland" refers to the Title with field's name omitted. All queried fields are joined with "AND" so that the results are narrowed down to all media items that only match those criteria in the query.

The current approach I've taken is by using my own QueryParser which I provide to the IQueryable.Where() method like the following:

    var queryParser = new SearchQueryParser(version, "title", analyzer);
    queryParser.DefaultOperator = QueryParser.Operator.AND;
    var query = queryParser.Parse(searchQuery);
    var result = provider.AsQueryable<MediaItem>().Where(query).ToList();

It seems to works to satisfy my need. Although I'm not so sure it's the correct way to achieve that. Thus I'd like to know if there's built-in mechanism I could use without providing my own QueryParser.

Thanks.

chriseldredge commented 10 years ago

If you are programmatically building the query you could achieve similar results by combining Where clauses:

var result = provider.AsQueryable<MediaItem>()
    .Where(i => i.Album == "sky")
    .Where(i => i.Artist == "alice")
    .Where(i => i.Genre == "pop")
    .Where(i => i.AnyField() == "wonderland");

Alternatively, you could also combine these into a single binary expression tree:

var result = provider.AsQueryable<MediaItem>().Where(
    i => i.Album == "sky"
    && i.Artist == "alice"
    && i.Genre == "pop"
    && i.AnyField() == "wonderland");

In either case the query translation will build a BooleanQuery that should have the same performance as using QueryParser.

If you are excepting queries like this from elsewhere your best bet is to stick with using QueryParser as you are doing now.

mahara commented 10 years ago

Hmm... IC. It seems using QueryParser approach is the only sensible way.

Thanks for the insight. And also thanks for creating this library. It really simplifies a lot the way I deal with Lucene.NET.