Exemplos de filtros no MongoDB (API C#)
Neste post vou demonstrar alguns exemplos simples de pesquisa no MongoDB utilizando a API .NET. Para o exemplo, eu vou considerar uma base local contendo a collection restaurants, a mesma que é usada na própria documentação do MongoDB. Além disso, vou construir uma tela Windows Forms.
A primeira coisa a ser feita é adicionar o MongoDB.Driver, e a melhor forma de fazer isso é através do Nuget. Basta selecionar a opção “Manage Nuget packages” ao se clicar com o botão direito em cima do projeto, no Solution Explorer. Como vemos na tela abaixo, basta preencher “MongoDB” na pesquisa que uma lista de pacotes é retornada. Note que se deve instalar o pacote MongoDB.Driver, tomando cuidado para não colocar a API antiga.
No nosso exemplo, faremos uma filtragem de restaurantes de acordo com vários parâmetros. Para isso, teremos uma ListBox para receber os resultados, uma combo para se escolher o filtro e um botão para executar a ação.
Esses filtros vamos carregar de forma dinâmica no exemplo, através de Reflection. Nosso critério será todos os métodos privados que sejam de instância (não sejam estáticos) e que cujo nome se inicie com “Filter”.
Para conectar na base do MongoDB, primeiro precisamos de um objeto do tipo MongoClient. Ele recebe como parâmetro a string de conexão, que no caso aponta para o MongoDB que eu tenho instalado na minha máquina. A partir desse objeto, usando o método GetDatabase nós obtemos uma referência a base que vamos trabalhar no MongoBD.
De forma a evitar repetição de código, eu criei um método genérico que recebe um objeto do tipo FilterDefinition e que obtém uma referência à collection que será pesquisada; executa a pesquisa passando o objeto FilterDefinition, obtendo uma lista através do método ToListAsync; e por fim formata essa lista resultante exibindo o nome, tipo de cozinha e localização. Este método é chamado ExecuteFilter.
O primeiro exemplo de filtro é do método FilterBrazilianRestaurants. Como o nome diz, ele faz a filtragem dos dados que trabalham com cozinha brasileira. O objeto filter é obtido a partir da classe Builders. Esse objeto possui um método Eq que cria uma cláusula de igualdade. No exemplo, serão procurados todos os registros que possuem o campo cuisine com valor Brazilian.
No método FilterBrazilianRestaurantsInManhattan as coisas começam a ficar interessantes. Veja que estamos juntando dois critérios de igualdade, com o operador &. Isso faz com que sejam pesquisados todos os registros com o campo cuisine igual a Brazilian e também todos que possuem o campo borough como Manhattan.
O terceiro método é o FilterBrazilianRestaurantsInManhattanOrDelicatessen, onde vemos um exemplo de como fazemos uma pesquisa usando o “ou”. Neste caso buscamos todos os restaurantes brasileiros em Manhattan ou todas as delicatessens.
Até agora usamos somente o operador Eq, mas a API permite usar também operações de maior, menor, etc.
Por fim, temos o método FilterBrazilianRestaurantsNearCoord, onde vamos fazer um exemplo de pesquisa por localização. O método Near recebe um ponto (coordenada no globo terrestre), a distância máxima e mínima, e retorna todos os registros que estejam próximos considerando este critério. Mas para isso funcionar corretamente, é necessário criar um índice no MongoDB com o comando abaixo.
db.restaurants.createIndex( { "address.coord": "2dsphere" } )
Com isso, eu termino por aqui o exemplo. Até a próxima.
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.GeoJsonObjectModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MongoDBAPIExample
{
public partial class Form1 : Form
{
private static IMongoClient _client;
private static IMongoDatabase _database;
public Form1()
{
InitializeComponent();
_client = new MongoClient("mongodb://localhost:27017");
_database = _client.GetDatabase("test");
var methods = GetType().GetTypeInfo().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
.Where(m => m.Name.StartsWith("Filter"));
foreach (var method in methods)
comboBox1.Items.Add(method.Name);
}
private async void button1_Click(object sender, EventArgs e)
{
var items = await (Task<List<string>>)GetType().GetTypeInfo()
.GetDeclaredMethod(comboBox1.SelectedItem.ToString())
.Invoke(this, null);
listBox1.Items.Clear();
foreach (var item in items)
{
listBox1.Items.Add(item);
}
label1.Text = string.Format("Total: {0}", items.Count);
}
private async Task<List<string>> ExecuteFilter(FilterDefinition<BsonDocument> filter)
{
var collection = _database.GetCollection<BsonDocument>("restaurants");
var result = await collection.Find(filter).ToListAsync();
return result.Select(i => string.Format("{0} ({1}) in {2}", i["name"], i["cuisine"], i["borough"])).ToList();
}
private async Task<List<string>> FilterBrazilianRestaurants()
{
var builder = Builders<BsonDocument>.Filter;
var filter = builder.Eq("cuisine", "Brazilian");
return await ExecuteFilter(filter);
}
private async Task<List<string>> FilterBrazilianRestaurantsInManhattan()
{
var builder = Builders<BsonDocument>.Filter;
var filter = builder.Eq("cuisine", "Brazilian") & builder.Eq("borough", "Manhattan");
return await ExecuteFilter(filter);
}
private async Task<List<string>> FilterBrazilianRestaurantsInManhattanOrDelicatessen()
{
var builder = Builders<BsonDocument>.Filter;
var filter = (builder.Eq("cuisine", "Brazilian") & builder.Eq("borough", "Manhattan"))
| builder.Eq("cuisine", "Delicatessen");
return await ExecuteFilter(filter);
}
private async Task<List<string>> FilterBrazilianRestaurantsNearCoord()
{
double lat = -73.9617039999, lng = 40.6629420000;
double maxDist = 1000, minDist = 10;
var point = new GeoJsonPoint<geojson2dcoordinates>(new GeoJson2DCoordinates(lat, lng));
var builder = Builders<BsonDocument>.Filter;
var filter = builder.Eq("cuisine", "Brazilian") &
builder.Near("address.coord", point, maxDist, minDist);
return await ExecuteFilter(filter);
}
}
}
Comentários
Postar um comentário