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); } } }
Nenhum comentário:
Postar um comentário