Este exemplo é inspirado no livro do Ayende
Se você deseja aprender RavenDB, recomendo que se inscreva no RavenDB bootcamp (é grátis). Se já conhece RavenDB, então o livro do Ayende é um excelente recurso.
Considere este documento:
{
"Company": "companies/62",
"Employee": "employees/7",
"OrderedAt": "1997-01-07T00:00:00.0000000",
"RequireAt": "1997-02-18T00:00:00.0000000",
"ShippedAt": "1997-01-13T00:00:00.0000000",
"ShipTo": {
"Line1": "Alameda dos Canàrios, 891",
"Line2": null,
"City": "Sao Paulo",
"Region": "SP",
"PostalCode": "05487-020",
"Country": "Brazil"
},
"ShipVia": "shippers/1",
"Freight": 108.04,
"Lines": [
{
"Product": "products/1",
"ProductName": "Chai",
"PricePerUnit": 14.4,
"Quantity": 10,
"Discount": 0
},
{
"Product": "products/21",
"ProductName": "Sir Rodney's Scones",
"PricePerUnit": 8,
"Quantity": 30,
"Discount": 0.1
},
{
"Product": "products/28",
"ProductName": "Rössle Sauerkraut",
"PricePerUnit": 36.4,
"Quantity": 42,
"Discount": 0.1
},
{
"Product": "products/36",
"ProductName": "Inlagd Sill",
"PricePerUnit": 15.2,
"Quantity": 5,
"Discount": 0.1
},
{
"Product": "products/40",
"ProductName": "Boston Crab Meat",
"PricePerUnit": 14.7,
"Quantity": 2,
"Discount": 0.1
}
]
}
O que fazer se desejarmos obter todos os pedidos contendo um produto em particular? Como seria a consulta?
var q =
from order in session.Query<Order>()
where order.Lines.Any(x => x.Product == "products/1")
select order;
Simples, não é?! Mas, como você save, todos as consultas ao RavenDB usam um índice. Se não há um índice para a consulta, RavenDB cria um automaticamente.
Aqui está o mapeamento do índice criado pelo RavenDB para essa consulta.
from doc in docs.Orders
select new {
Lines_Product = (
from docLinesItem in ((IEnumerable<dynamic>)doc.Lines).DefaultIfEmpty()
select docLinesItem.Product).ToArray()
}
A coisa interessante aqui é o uso de um array de strings. Quando RavenDB encontra uma coleção em um campo de índice, a indexação ocorre múltiplas vezes. Outro conceito importante é que o RavenDB irá “achatar” todas as coleções.
Então, vamos definir um índice nós mesmos.
public class Orders_SearchByProduct :
AbstractIndexCreationTask<Order, Orders_SearchByProduct.QueryModel>
{
public class QueryModel
{
public string Query;
}
public Orders_SearchByProduct()
{
Map = orders =>
from order in orders
select new
{
Query = new object[]
{
order.Lines.Select(p => p.Product).ToArray(),
order.Lines.Select(p => p.ProductName).ToArray()
}
};
}
}
Agora, podemos procurar pedidos que contenham um produto em específico considerando tanto o Id quanto o nome. Eis um exemplo:
using (var session = DocumentStoreHolder.Store.OpenSession())
{
var q =
session.Query<Orders_SearchByProduct.QueryModel,Orders_SearchByProduct>()
.Where(o => o.Query == "Manjimup Dried Apples")
.OfType<Order>();
foreach (var order in q.ToList())
{
Console.WriteLine(order.Id);
}
}
O operador OfType é usado para mudar o tipo do resultado.
Era isso.