-
Notifications
You must be signed in to change notification settings - Fork 73
Getting Started
ElasticLINQ is an implementation of the LINQ Query Provider that allows developers to search their Elasticsearch object store and return the resulting documents as CLR classes. This leverages the developer's experience with LINQ and relational data stores, and eases the transition into distributed NoSQL data stores.
As with most open source libraries for .NET, ElasticLINQ binaries are available via NuGet. Just install the package ElasticLINQ into your project. Currently, we support Desktop .NET 4.5 and later.
To get started, you will need an Elasticsearch server (or server cluster). It can be installed on both Windows and Linux, with installation instructions found here. The Elasticsearch API is done via HTTP and JSON, so you will need to be able to have HTTP access to the server (on port 9200, with a default installation).
Elasticsearch segregates data into what's called an index (think of this as a database in a traditional data world). When searching Elasticsearch, you can narrow your search to one or more indices, or you can search all the indices in the server cluster.
To start, you will need to create the connection object which instructs ElasticLINQ how to connect to the server:
var connection = new ElasticConnection(new Uri("http://myserver:9200"));
There are four additional optional constructor arguments: username
and password
for servers that require authentication, a timeout
value to tell Elasticsearch how long you're willing to wait for an answer, and an index
parameter to tell Elasticsearch which index to search (to search multiple indices, pass a comma-separated string like "index1,index2"
).
Once you have the connection object, you'll need to create the context object; this object is where your queries will start.
var context = new ElasticContext(connection);
This constructor, too, has optional arguments: a mapping
object which controls query generation options, a retryPolicy
object which allows you to specify retry logic for failed searchs, and a log object
that lets you integrate ElasticLINQ's logging into your existing logging solution.
The context object's Query<T>
method starts a query against a particular document type in Elasticsearch, and returns an IQueryable<T>
.
IQueryable<Person> query = context.Query<Person>();
From here, you can use many of the traditional LINQ operations which will be translated into an Elasticsearch request.
As of version 1.0, the following LINQ operations are supported: Where
, Skip
, Take
, Select
, OrderBy
and OrderByDescending
, ThenBy
and ThenByDescending
, First
and FirstOrDefault
, and Single
and SingleOrDefault
.
As with any LINQ implementation, there are limitations on the types of queries that are supported, since your C# code must be translate into an appropriate query at runtime. The Where operation supports most common expressions, including: ==
, !=
, <
, <=
, >
, >=
, ||
, and &&
; as well as Equals
and Contains
.
Elasticsearch offers a full text search feature called query_string
. It's intended to take user input (which means searches are case-insensitive), and lets the user specify things like wildcards and join operators like AND
and OR
. To issue a query_string
search, use the QueryString
extension method on your IQueryable<T>
:
query.QueryString("this AND that OR the other thing")
For more information on full-text searching with query_string
, see the Elasticsearch documentation.
In addition to the built-in LINQ operations, ElasticLINQ also supports four custom operations implemented as static methods on the ElasticMethods
class: Regexp
, Prefix
, ContainsAny
, and ContainsAll
. The first two are fairly self explanatory; the latter two require a bit of background.
Since LINQ (and relational databases) really don't support the notion of columns which are themselves collections, there is no existing syntax that adequately expresses the idea of matching collections against collections. The Contains
method will do the one-to-many mapping, and is supported in both directions with ElasticLINQ as you'll see below. When you have a collection field, and you want to see if it matches any (or all) of the values in a list, you can use ElasticMethods.ContainsAny
or ElasticMethods.ContainsAll
to express that style of query.
Here are the four types of collection-related queries:
var names = new[] { "Brad", "Jim", "Damien" };
// See if a field matches one of many values
query.Where(x => names.Contains(x.Name))
// See if a collection field contains a single value
query.Where(x => x.Aliases.Contains("Brad"))
// See if a collection field contains any value from a list
query.Where(x => ElasticMethods.ContainsAny(x.Aliases, names))
// See if a collection field contains all values from a list
query.Where(x => ElasticMethods.ContainsAll(x.Aliases, names))
When querying (with Where
and Query
) and projecting (with Select
), you have access to two pieces of metadata from Elasticsearch
: the document ID, and the search score. These fields are available as static properties named ElasticFields.Id
and ElasticFields.Score
, respectively.
A note about scoring: in Elasticsearch (and Lucene), a search is performed in two stages: a query
, which scores the results of the search, and a filter
, which further filters the result of the query
. The default query
and filter
return all documents, so you can query
without a filter
, filter
without a query
, or provide neither (and simply get all the documents in Elasticsearch).
When you use Where
in ElasticLINQ, that translates into a filter
. We chose this by default because it is significantly faster than a query
, and the results of filter
are cacheable by Elasticsearch. If you don't intend to use scoring, then filter
is the way to go. If you want to issue a query
so you can get scoring (for example, because you're doing full-text style searching), you can use the Query
extension method that we've added to IQueryable
; it has the same syntax and usage as Where
, except that it results in a query for your search. You can mix both Query
and Where
in the same request, but be aware that the two-stage system in Elasticsearch means that all Query
criteria will be searched before any Where
criteria are.