Querying: Filteringg
One of the most basic functionalities of querying is the ability to filter out data and return records that match a given condition. There are couple of ways to do this and they all depend on the querying approach you want to use (Queryfrom basic session operations, DocumentQuery from advanced session operations, or directly using RQL).
The following examples demonstrate how to add simple conditions to a query using all of those methods.
Where
IList<Employee> results = session
.Query<Employee, Employees_ByFirstAndLastName>() // query 'Employees/ByFirstAndLastName' index
.Where(x => x.FirstName == "Robert" && x.LastName == "King") // filtering predicates
.ToList(); // materialize query by sending it to server for processing
IList<Employee> results = session
.Advanced
.DocumentQuery<Employee, Employees_ByFirstAndLastName>() // query 'Employees/ByFirstAndLastName' index
.WhereEquals(x => x.FirstName, "Robert") // filtering predicates
.AndAlso() // by default OR is between each condition
.WhereEquals(x => x.LastName, "King") // filtering predicates
.ToList(); // materialize query by sending it to server for processing
public class Employees_ByFirstAndLastName : AbstractIndexCreationTask<Employee>
{
public Employees_ByFirstAndLastName()
{
Map = employees => from employee in employees
select new
{
FirstName = employee.FirstName,
LastName = employee.LastName
};
}
}
from index 'Employees/ByFirstAndLastName'
where FirstName = 'Robert' and LastName = 'King'
Where - Numeric Property
IList<Product> results = session
.Query<Product, Products_ByUnitsInStock>() // query 'Products/ByUnitsInStock' index
.Where(x => x.UnitsInStock > 50) // filtering predicates
.ToList(); // materialize query by sending it to server for processing
IList<Product> results = session
.Advanced
.DocumentQuery<Product, Products_ByUnitsInStock>() // query 'Products/ByUnitsInStock' index
.WhereGreaterThan(x => x.UnitsInStock, 50) // filtering predicates
.ToList(); // materialize query by sending it to server for processing
private class Products_ByUnitsInStock : AbstractIndexCreationTask<Product>
{
public Products_ByUnitsInStock()
{
Map = products => from product in products
select new
{
product.UnitsInStock
};
}
}
from index 'Products/ByUnitsInStock'
where UnitsInStock > 50
Where - Nested Property
// return all orders that were shipped to 'Albuquerque'
IList<Order> results = session
.Query<Order>()
.Where(x => x.ShipTo.City == "Albuquerque")
.ToList();
// return all orders that were shipped to 'Albuquerque'
IList<Order> results = session
.Advanced
.DocumentQuery<Order>()
.WhereEquals(x => x.ShipTo.City, "Albuquerque")
.ToList();
from Orders
where ShipTo.City = 'Albuquerque'
IList<Order> results = session
.Query<Order, Order_ByOrderLinesCount>() // query 'Order/ByOrderLinesCount' index
.Where(x => x.Lines.Count > 50) // filtering predicates
.ToList(); // materialize query by sending it to server for processing
IList<Order> results = session
.Advanced
.DocumentQuery<Order, Order_ByOrderLinesCount>() // query 'Order/ByOrderLinesCount' index
.WhereGreaterThan(x => x.Lines.Count, 50) // filtering predicates
.ToList(); // materialize query by sending it to server for processing
private class Order_ByOrderLinesCount : AbstractIndexCreationTask<Order>
{
public Order_ByOrderLinesCount()
{
Map = orders => from order in orders
select new
{
Lines_Count = order.Lines.Count
};
}
}
from index 'Order/ByOrderLinesCount'
where Lines.Count > 50
Where + Any
Any
is useful when you have a collection of items (e.g. Order
contains OrderLines
) and you want to filter out based on values from this collection. For example, let's retrieve all orders that contain an OrderLine
with a given product.
IList<Order> results = session
.Query<Order, Order_ByOrderLines_ProductName>() // query 'Order/ByOrderLines/ProductName' index
.Where(x => x.Lines.Any(l => l.ProductName == "Teatime Chocolate Biscuits")) // filtering predicates
.ToList(); // materialize query by sending it to server for processing
IList<Order> results = session
.Advanced
.DocumentQuery<Order, Order_ByOrderLines_ProductName>() // query 'Order/ByOrderLines/ProductName' index
.WhereEquals("Lines_ProductName", "Teatime Chocolate Biscuits") // filtering predicates
.ToList(); // materialize query by sending it to server for processing
public class Order_ByOrderLines_ProductName : AbstractIndexCreationTask<Order>
{
public Order_ByOrderLines_ProductName()
{
Map = orders => from order in orders
select new
{
Lines_ProductName = order.Lines.Select(x => x.ProductName)
};
}
}
from index 'Order/ByOrderLinesCount'
where Lines_ProductName = 'Teatime Chocolate Biscuits'
Where + In
When you want to check a single value against multiple values, the In
operator can become handy. To retrieve all employees where FirstName
is either Robert
or Nancy
, we can issue the following query:
IList<Employee> results = session
.Query<Employee, Employees_ByFirstAndLastName>() // query 'Employees/ByFirstAndLastName' index
.Where(x => x.FirstName.In("Robert", "Nancy")) // filtering predicates (remember to add `Raven.Client.Linq` namespace to usings)
.ToList(); // materialize query by sending it to server for processing
IList<Employee> results = session
.Advanced
.DocumentQuery<Employee, Employees_ByFirstAndLastName>() // query 'Employees/ByFirstAndLastName' index
.WhereIn(x => x.FirstName, new[] { "Robert", "Nancy" }) // filtering predicates
.ToList(); // materialize query by sending it to server for processing
public class Employees_ByFirstAndLastName : AbstractIndexCreationTask<Employee>
{
public Employees_ByFirstAndLastName()
{
Map = employees => from employee in employees
select new
{
FirstName = employee.FirstName,
LastName = employee.LastName
};
}
}
from index 'Employees/ByFirstAndLastName'
where FirstName IN ('Robert', 'Nancy')
Important
Remember to add the Raven.Client.Documents.Linq
namespace to usings if you want to use In
extension method.
Where + ContainsAny
To check if enumeration contains any of the values from a specified collection, you can use the ContainsAny
method.
Let's assume that we want to return all BlogPosts
that contain any of the specified Tags
.
IList<BlogPost> results = session
.Query<BlogPost, BlogPosts_ByTags>() // query 'BlogPosts/ByTags' index
.Where(x => x.Tags.ContainsAny(new[] { "Development", "Research" })) // filtering predicates (remember to add `Raven.Client.Linq` namespace to usings)
.ToList(); // materialize query by sending it to server for processing
IList<BlogPost> results = session
.Advanced
.DocumentQuery<BlogPost, BlogPosts_ByTags>() // query 'BlogPosts/ByTags' index
.ContainsAny("Tags", new[] { "Development", "Research" }) // filtering predicates
.ToList(); // materialize query by sending it to server for processing
public class BlogPosts_ByTags : AbstractIndexCreationTask<BlogPost>
{
public BlogPosts_ByTags()
{
Map = posts => from post in posts
select new
{
post.Tags
};
}
}
from index 'BlogPosts/ByTags'
where Tags IN ('Development', 'Research')
Important
Remember to add the Raven.Client.Documents.Linq
namespace to usings if you want to use the ContainsAny
extension method.
Where + ContainsAll
To check if an enumeration contains all of the values from a specified collection, you can use the ContainsAll
method.
Let's assume that we want to return all the BlogPosts
that contain all of the specified Tags
.
IList<BlogPost> results = session
.Query<BlogPost, BlogPosts_ByTags>() // query 'BlogPosts/ByTags' index
.Where(x => x.Tags.ContainsAll(new[] { "Development", "Research" })) // filtering predicates (remember to add `Raven.Client.Linq` namespace to usings)
.ToList(); // materialize query by sending it to server for processing
IList<BlogPost> results = session
.Advanced
.DocumentQuery<BlogPost, BlogPosts_ByTags>() // query 'BlogPosts/ByTags' index
.ContainsAll("Tags", new[] { "Development", "Research" }) // filtering predicates
.ToList(); // materialize query by sending it to server for processing
public class BlogPosts_ByTags : AbstractIndexCreationTask<BlogPost>
{
public BlogPosts_ByTags()
{
Map = posts => from post in posts
select new
{
post.Tags
};
}
}
from index 'BlogPosts/ByTags'
where Tags ALL IN ('Development', 'Research')
Important
Remember to add the Raven.Client.Documents.Linq
namespace to usings if you want to use the ContainsAll
extension method.
Where - StartsWith
// return all products which name starts with 'ch'
IList<Product> results = session
.Query<Product>()
.Where(x => x.Name.StartsWith("ch"))
.ToList();
// return all products which name starts with 'ch'
IList<Product> results = session
.Advanced
.DocumentQuery<Product>()
.WhereStartsWith(x => x.Name, "ch")
.ToList();
from Products
where startsWith(Name, 'ch')
Where - EndsWith
// return all products which name ends with 'ra'
IList<Product> results = session
.Query<Product>()
.Where(x => x.Name.EndsWith("ra"))
.ToList();
// return all products which name ends with 'ra'
IList<Product> results = session
.Advanced
.DocumentQuery<Product>()
.WhereEndsWith(x => x.Name, "ra")
.ToList();
from Products
where endsWith(Name, 'ra')
Remarks
Information
Underneath, Query
and DocumentQuery
are converting predicates to the IndexQuery
class so they can issue a query from a low-level operation method.