.NET Framework

Criar uma pesquisa empresarial para .NET

Damian Zapart

Baixar o código de exemplo

A emergência da computação em nuvem nos últimos anos tem sido uma vantagem para organizações e usuários semelhantes. As organizações podem conhecer seus clientes como nunca antes e direcioná-lo com comunicações personalizadas. Os usuários podem obter seus dados a partir de praticamente qualquer lugar, tornando-os mais acessíveis e úteis. Têm sido construídos grandes data centers em todo o mundo para armazenar todos esses dados. Mas grandes volumes de dados levam a grandes desafios.

A citação conhecida de John Naisbitt “Estamos nos afogando em informação, mas sedentos por conhecimento” em seu livro “Megatrends: Ten New Directions Transforming Our Lives” (Warner Books, 1982), descreve perfeitamente a situação atual no mercado de Big Data. As empresas são capazes de armazenar petabytes de dados, mas serem capazes de perceber esses dados e torná-los pesquisáveis é muito mais difícil, especialmente pois a maioria dos data warehouses armazenam dados de forma não estruturada (NoSQL) em múltiplas coleções em repositórios de Big Data ou mesmo em uma forma distribuída entre diferentes warehouses. Além disso, há uma variedade de formatos de dados, tais como documentos JSON, arquivos do Microsoft Office e assim por diante. Pesquisar através de uma única coleção não estruturada não costuma ser um problema, mas é muito mais difícil procurar todos os dados não estruturados em múltiplas coleções para encontrar somente um pequeno subconjunto particular de resultados quando o usuário não faz ideia onde possa estar. É aqui que a pesquisa empresarial entra em cena.

Pesquisa Empresarial

Eis o desafio essencial da pesquisa empresarial: Como pode uma grande organização com várias fontes de dados fornecer aos usuários internos e externos a habilidade de procurar todas as fontes de dados da empresa pública através de uma interface? Essa interface única pode ser uma API, o site de uma empresa ou somente uma caixa de texto simples com funcionalidade de preenchimento automático implementada de modo subjacente. Independentemente da interface que uma empresa escolhe, deve fornece a habilidade de procurar em todo seu universo de dados, o que pode incluir bancos de dados estruturados e não estruturados, documentos de intranet em diferentes formatos, outras APIs e outros tipos de fontes de dados.

Como pesquisar por meio de múltiplos conjuntos de dados é bastante complexo, há somente algumas soluções de pesquisa empresarial reconhecidas e a fasquia está elevada. Uma solução de pesquisa empresarial deve incluir os seguintes recursos:

  • Reconhecimento de conteúdo: Saber onde tipos particulares de dados podem ser localizados.
  • Indexação em tempo real: Manter todos os dados indexados.
  • Processamento de conteúdo: Tornar diferentes fontes de dados acessíveis.

Uma das soluções de pesquisa empresarial mais populares é Elasticsearch livre (elasticsearch.org). Este servidor baseado em Java criado sobre Apache Lucene (lucene.apache.org) fornece uma pesquisa escalonáveis e de texto completo em fontes de dados, com suporte JSON e uma interface da Web REST, vem como alta disponibilidade, gerenciamento de conflito e análise em tempo real. Visite bit.ly/1vzoUrR para ver seu conjunto completo de recursos.

De um nível superior, a forma como Elasticsearch armazena data é muito simples. O elemento superior da estrutura em um servidor é chamado um índice e podem existir múltiplos índices no mesmo armazenamento de dados. O índice é somente um contêiner de documentos (um ou mais) e cada documento é uma coleção de um ou mais campos (sem estrutura definida). Cada índice pode conter dados agregados em unidades chamadas tipos, que representam grupos lógicos de dados em um índice particular.

Talvez seja útil pensar no Elasticsearch como algo parecido com uma tabela do mundo dos bancos de dados relacionais. A mesma correlação existe entre as linhas e colunas de uma tabela e os documentos e campos de um índice, em que um documento corresponde a uma linha e um campo a uma coluna. No entanto, com Elasticsearch, não há estrutura de dados fixos ou esquema de banco de dados.

Como observado, os desenvolvedores podem comunicar com o servidor Elasticsearch através de uma interface da Web REST. Isto significa que podem consultar índices, tipos, dados ou outras informações do sistema somente enviando solicitações da Web REST de um navegador ou qualquer outro tipo de cliente da Web. Eis alguns exemplos de solicitações GET:

  • Consulta para todos os índices:
           http://localhost:9200/_cat/indices/?v
  • Consulta de metadados do índice:
           http://localhost:9200/clients/_stats
  • Consulta para todos os dados de índice: 
           http://localhost:9200/clients/_search?q=*:*
  • Procura para um valor de campo específico no índice: 
           http://localhost:9200/clients/_search?q=field:value
  • Obter todos os dados no tipo de mapeamento de índice:
           http://localhost:9200/clients/orders/_search?q=*:*

Criar uma pesquisa

Para demonstrar como criar uma solução simples e com várias fontes, vou usar Elasticsearch 1.3.4 com documentos JSON, documentos PDF e um banco de dados SQL Server. Para começar, vou descrever brevemente a configuração de Elasticsearch e, em seguida, demonstrar como conectar cada fonte de dados para tornar os dados pesquisáveis. Para manter as coisas simples, vou apresentar um exemplo muito próximo da realidade que usa fontes de dados de uma empresa Contoso conhecida.

Vou usar um banco de dados SQL Server 2014 com múltiplas tabelas, embora só vá usar uma, dbo.Orders. Como o nome da tabela sugere, armazena registros sobre os pedidos dos clientes da empresa – um grande número de registros, porém fácil de gerenciar:

CREATE TABLE [dbo].[Orders]
(
  [Id] [int] IDENTITY(1,1) NOT NULL primary key,
  [Date] [datetime] NOT NULL,
  [ProductName] [nvarchar](100) NOT NULL,
  [Amount] [int] NOT NULL,
  [UnitPrice] [money] NOT NULL
);

Também tenho um compartilhamento de rede com múltiplos documentos da empresa organizados em uma hierarquia de pastas. Os documentos estão relacionados com campanhas de marketing de diferentes produtos organizadas pela empresa no passado e são armazenados em múltiplos formatos, incluindo PDF e Microsoft Office Word. O tamanho médio do documento é cerca de 1 MB.

Por fim, tenho uma API de empresa interna que expõe as informações de cliente da empresa no formato JSON; como sei a estrutura da resposta, posso facilmente desserializá-la para um objeto do cliente tipo. Meu objetivo é tornar todas as fontes de dados pesquisáveis usando o mecanismo de Elasticsearch. Além disso, quero criar um serviço Web baseado em Web API 2 que, no modo subjacente, irá executar uma consulta empresarial em todos os índices fazendo uma única chamada ao servidor Elasticsearch. (Obtenha mais informações sobre Web API 2 em bit.ly/1ae6uya.) O serviço Web devolverá os resultados como uma lista de sugestões com potenciais dicas para o usuário final; tal lista pode ser consumida mais tarde por um controle de preenchimento automático inserido no aplicativo ASP.NET MVC ou por qualquer outro tipo de site.

Configurando

A primeira coisa a fazer é instalar o servidor Elasticsearch. Para Windows, é possível fazê-lo manual ou automaticamente, com o mesmo resultado — um serviço Windows em execução hospedando o servidor Elasticsearch. A instalação automática é muito rápida e fácil; tudo o que precisa fazer é baixar e executar o instalador do Elasticsearch MSI (bit.ly/12RkHDz). Infelizmente, não há outra forma de escolher uma versão Java ou, muito mais importante, uma versão de Elasticsearch. O processo de instalação manual, por outro lado, requer um pouco mais de esforço, mas permite um maior controle sobre os componentes pelo que é mais adequado neste caso.

Configurar o Elasticsearch como um serviço do Windows manualmente requer as seguintes etapas:

  1. Baixe e instale o Java SE Runtime Environment mais recente (bit.ly/1m1oKlp).
  2. Adicione a variável de ambiente chamada JAVA_HOME. Seu valor será o caminho da pasta em que instalou Java (por exemplo, C:\Arquivos de Programas\Java\jre7), como mostrado na Figura 1.
  3. Baixe o arquivo do Elasticsearch (bit.ly/1upadla) e descompacte-o.
  4. Mova as fontes descompactadas para Arquivos de Programas | Elasticsearch (opcional).
  5. Execute o prompt de comando como um administrador e execute service.bat com o parâmetro de instalação:
           C:\Arquivos de Programas\Elasticsearch\elasticsearch-1.3.4\bin>service.bat install

Definindo a variável de ambiente Java_Home
Figura 1 Definindo a variável de ambiente Java_Home

É tudo o que precisa para obter o serviço do Windows em funcionamento, com o servidor Elasticsearch acessível no localhost, na porta 9200. Agora posso fazer uma solicitação da Web para a URL http://localhost:9200/ através de qualquer navegador da Web e obterei uma resposta com esta aparência:

{
  "status" : 200,
  "name" : "Washout",
  "version" : {
    "number" : "1.3.4",
    "build_hash" : "a70f3ccb52200f8f2c87e9c370c6597448eb3e45",
    "build_timestamp" : "2014-09-30T09:07:17Z",
    "build_snapshot" : false,
    "lucene_version" : "4.9"
  },
  "tagline" : "You Know, for Search"
}

Agora minha instância local do Elasticsearch está pronta; no entanto, a versão bruta não me dá a habilidade de conectar ao SQL Server ou executar uma pesquisa de texto completo através dos arquivos de dados. Para disponibilizar estes recursos, também tenho de instalar vários plug-ins.

Estendendo Elasticsearch

Como mencionei, a versão bruta do Elasticsearch não deixa indexar uma fonte de dados externa como SQL Server, Office ou até mesmo um PDF. Para tornar estas fontes de dados pesquisáveis preciso instalar alguns plug-ins, o que é bastante fácil.

Meu primeiro objetivo é fornecer suporte de pesquisa de texto completo para anexos. Com anexo, quero dizer uma representação codificada em base64 do arquivo de origem que foi atualizado para um armazenamento de dados Elasticsearch como um documento JSON. (Consulte bit.ly/12RGmvg para obter informações sobre o tipo de anexo.) O plug-in que necessito para esta finalidade é o Tipo de Anexos do Mapeador para a versão 2.3.2 do Elasticsearch, disponível em bit.ly/1Alj8sy. Esta é a extensão do Elasticsearch que permite uma pesquisa de texto completo para documentos e baseia-se no projeto Apache Tika (tika.apache.org), que detecta e extrai metadados e conteúdo de texto de vários tipos de documentos e fornece suporte para os formatos de arquivo listados em bit.ly/1qEyVmr.

Como com a maioria dos plug-ins para Elasticsearch, esta instalação é extremamente simples e tudo o que preciso fazer é executar o prompt de comando como um administrador e executar o seguinte comando:

bin>plugin --install elasticsearch/elasticsearch-mapper-attachments/2.3.2

Após baixar e extrair o plug-in, preciso reiniciar o serviço do Windows do Elasticsearch.

Quando estiver concluído, preciso configurar o suporte do SQL Server. É claro que também há um plug-in para isto. É chamado JDBC River (bit.ly/12CK8Zu) e permite buscar dados de uma fonte JDBC, tal como SQL Server, para indexação no Elasticsearch. O plug-in é facilmente instalado e configurado, embora o processo de instalação tenha três fases que precisam ser concluídas.

  1. Primeiro, instalei o Microsoft JDBC Driver 4.0, um provedor de dados baseado em Java de SQL Server que pode ser baixado de bit.ly/1maiM2j. O aspecto importante a lembrar é a necessidade de extrair o conteúdo de um arquivo baixável para a pasta chamada Microsoft JDBC Driver 4.0 para SQL Server (que precisa ser criada se não existir), diretamente sob a pasta Arquivos de Programas, pelo que o caminho resultante se parece como: C:\Arquivos de Programas\Microsoft JDBC Driver 4.0 para SQL Server.
  2. Em seguida, instalo o plug-in usando o seguinte comando:
           bin> plugin --install
           jdbc --url "http://xbib.org/repository/org/xbib/elasticsearch/plugin/elasticsearch-river-jdbc/1.3.4.4/elasticsearch-river-jdbc-1.3.4.4-plugin.zip"
  3. Por fim, copio o arquivo SQLJDBC4.jar extraído na primeira etapa (C:\Arquivos de Programas\Microsoft JDBC DRIVER 4.0 para SQL Server\sqljdbc_4.0\enu\SQLJDBC4.jar) para o arquivo lib no diretório Elasticsearch (C:\Arquivos de Programas\Elasticsearch\lib). Quando terminar, preciso lembrar-me de reiniciar o serviço do Windows.

Agora todos os plug-ins necessários foram instalados. No entanto, para verificar as instalações terminadas corretamente, preciso enviar os seguintes comandos como uma solicitação HTTP GET:

http://localhost:9200/_nodes/_all/plugins

Na resposta, espero ver ambos os plug-ins instalados listados, conforme mostrado na Figura 2.

Os plug-ins instalados
Figura 2 Os plug-ins instalados

Configurar o SQL Server

Para usar JDBC River com SQL Server, a instância do SQL Server precisa ser acessível via TCP/IP, que, por padrão, está desativada. No entanto, habilitá-la é simples e tudo o que preciso é abrir o do SQL Server Configuration Manager e, na Configuração de Rede do SQL Server, para a instância do SQL Server à qual me quero conectar, altere o valor Status para Habilitar protocolo TCP/IP, conforme mostrado na Figura 3. Depois de o fazer, devo ser capaz de fazer logon na minha instância do SQL Server por meio do Management Studio usando localhost 1433 no nome do servidor (a porta 1433 é a porta padrão para acessar SQL Server via TCP/IP).

Habilitar TCP/IP para a instância do SQL Server
Figura 3 Habilitar TCP/IP para a instância do SQL Server

Tornar fontes pesquisáveis

Todos os plug-ins necessários foram instalados, pelo que agora é o momento de carregar os dados. Como mencionado anteriormente, eu tenho três fontes de dados diferentes (documentos JSON, arquivos e uma tabela de pedidos de um banco de dados do SQL Server) que eu desejo indexar no Elasticsearch. Posso indexar estas fontes de dados de muitas formas diferentes, mas quero demonstrar quão fácil é usar um aplicativo baseado em .NET que implementei. Como tal, como uma precondição de indexação, preciso instalar uma biblioteca externa chamada NEST (bit.ly/1vZjtCf) para meu projeto, que não é nada, mas um invólucro gerenciado em uma interface da Web Elasticsearch. Como esta biblioteca está disponível no NuGet, tornando-a parte de meu projeto é tão simples como executar um comando simples no Console do Gerenciador de Pacotes:

PM> Install-Package NEST

Agora, com a biblioteca NEST disponível em minha solução, posso criar um novo projeto de biblioteca de classe chamado ElasticSearchRepository. Usei este nome pois decide manter todas as chamadas de função da classe ElasticClient (que é parte da biblioteca NEST) separadas do resto da solução. Ao fazer isso, o projeto fica semelhante ao padrão de design do repositório amplamente aplicado em aplicativos baseados no Entity Framework, pelo que será fácil de compreender. Além disso, neste projeto tenho somente três classes: a classe BaseRepository, que inicializa e expõe as classes herdadas e a instância do ElasticClient e as outras duas classes de repositório:

  • IndexRepository — uma classe de leitura/gravação que usarei para manipular índices, definir mapeamentos e carregar documentos.
  • DiscoveryRepository — uma classe somente leitura que usarei durante operações de pesquisa baseadas em API.

A Figura 4 mostra a estrutura da classe BaseRepository com uma propriedade protegida do tipo ElasticClient. Este tipo, fornecido como parte da biblioteca NEST, centraliza a comunicação entre o servidor Elasticsearch e o aplicativo cliente. Para criar uma instância do mesmo, posso transmitir uma URL ao servidor Elasticsearch, que transmitirei como um parâmetro do construtor de classe opcional. Se o parâmetro for nulo, um valor padrão de http://localhost:9200 será usado.

Figura 4 A classe BaseRepository

namespace ElasticSearchRepository
{
  using System;
  using Nest;
  public class BaseRepository
  {
    protected ElasticClient client;
    public BaseRepository(Uri elastiSearchServerUrl = null)
    {
      this.client = elastiSearchServerUrl != null ?
        new ElasticClient(new ConnectionSettings(elastiSearchServerUrl)) :
        : new ElasticClient();
    }
  }
}

Com o cliente pronto, primeiro indexarei os dados cliente; este é o cenário mais fácil, pois não são necessários plug-ins adicionais:

public class Client
{
  public int Id { get; set; }
  public string Name { get; set; }
  public string Surname { get; set; }
  public string Email { get; set; }
}

Para indexar este tipo de dados, invoco a instância de meu cliente Elasticsearch, bem como a função Index<T>, em que T é o tipo de minha classe Client, que representa dados serializados devolvidos da API. Esta função genérica assume três parâmetros: a instância da classe de objeto T, um nome de índice de destino e um nome de mapeamento no índice:

public bool IndexData<T>(T data, string indexName =
  null, string mappingType = null)
  where T : class, new()
  {
    if (client == null)
    {
      throw new ArgumentNullException("data");
    }
    var result = this.client.Index<T>(data,
      c => c.Index(indexName).Type(mappingType));
    return result.IsValid;
  }

Os últimos dois parâmetros são opcionais pois NEST aplicará sua lógica padrão para criar um nome de índice de destino baseado no tipo genérico.

Agora quero indexar os documentos de marketing, que estão relacionados aos produtos da empresa. Como tenho esses arquivos armazenados em um compartilhamento de rede, posso incluir as informações sobre cada documento específico em uma classe MarketingDocument simples. É importante observar aqui que se eu quiser um documento indexado em Elasticsearch, preciso carregá-lo como uma cadeia de caracteres codificada em Base64:

public class MarketingDocument
{
  public int Id { get; set; }
  public string Title { get; set; }
  public string ProductName { get; set; }
  // Base64-encoded file content.
  public string Document { get; set; }
}

A classe está pronta, portanto, posso usar o ElasticClient para marcar um campo particular em minha classe MarketingDocument como um anexo. Posso obtê-lo criando um novo índice chamado "produtos" e adicionando um novo mapeamento de marketing a ele (para simplificar, o nome da classe será o nome do mapeamento):

private void CreateMarketingIndex()
  {
    client.CreateIndex("products", c =>
      c.AddMapping<Marketing>
      (m => m.Properties(ps =>ps.Attachment(a =>
            a.Name(o =>o.Document).TitleField(t =>
            t.Name(x => x.Name)
            TermVector(TermVectorOption.WithPositionsOffsets)
        )))));
  }

Agora que tenho o tipo .NET e o mapeamento de dados de marketing, bem como a definição de um anexo, posso começar a indexação de meus arquivos da mesma forma que eu indexei os dados do cliente:

var documents = GetMarketingDocumentsMock();
documents.ForEach((document) =>
{
  indexRepository.IndexData<MarketingDocument>(document, "marketing");
});

A etapa final é a configuração JDBC River em Elasticsearch. Infelizmente, NEST ainda não suporta JDBC River. Em teoria, posso criar um mapeamento de JDBC River usando uma função Raw para enviar uma solicitação bruta com JSON, mas não quero complicar demais as coisas. Portanto, para concluir o processo de criação do mapeamento, vou especificar os seguintes parâmetros:

  • Uma cadeia de conexão para o banco de dados do SQL Server
  • Uma consulta SQL, que será usada para consultar dados
  • Agenda de atualização
  • Nome e tipo do índice de destino (opcional)

(Encontrará uma lista completa de parâmetros configuráveis em bit.ly/12CK8Zu.)

Para criar um novo mapeamento de JDBC River, preciso enviar uma solicitação de PUT com um corpo de solicitação especificado para a seguinte URL: 

http://localhost:9200/_river/{river_name}/_meta

No exemplo na Figura 5, coloco um corpo de solicitação para criar um mapeamento de JDBC River, que se conecta ao banco de dados da Contoso hospedado na instância do SQL Server local, que está acessível na porta 1433 via TCP/IP.

Figura 5 Solicitação HTTP PUT para criar um novo mapeamento de JDBC River

PUT http://localhost:9200/_river/orders_river/_meta
{
"type":"jdbc",
"jdbc":
  {
  "driver": "com.microsoft.sqlserver.jdbc.SQLServerDriver",
  "url":"jdbc:sqlserver://127.0.0.1:1433;databaseName=Contoso",
  "user":"elastic",
  "password":"asd",
  "sql":"SELECT *  FROM dbo.Orders",
  "index" : "clients",
  "type" : "orders",
  "schedule": "0/30 0-59 0-23 ? * *"
  }
}

Usa o logon “elastic” e a senha “asd” para autenticar o usuário e executar o seguinte comando SQL:

SELECT * FROM dbo.Orders

Cada linha de dados devolvida por esta consulta SQL será indexada no índice de clientes no tipo de mapeamento de pedidos e a indexação ocorrerá a cada 30 segundos (representada na notação Cron, consulte bit.ly/1hCcmnN para mais informações).

Quando este processo for concluído, verá no arquivo de log do Elasticsearch (/logs/ elasticsearch.log) informações semelhantes às seguintes:

[2014-10-2418:39:52,190][INFO][river.jdbc.RiverMetrics]
pipeline org.xbib.elasticsearch.plugin.jdbc.RiverPipeline@70f0a80d
complete: river jdbc/orders_river metrics: 34553 rows, 6.229481683638776 mean, 
  (0.0 0.0 0.0), ingest metrics: elapsed 2 seconds, 
  364432.0 bytes bytes, 1438.0 bytes avg, 0.1 MB/s

Se algo estiver errado com a configuração river, a mensagem de erro também estará no log.

Pesquisando os dados

Assim que todos os dados tiver sido indexados no mecanismo Elasticsearch, posso começar consultando. É claro que posso enviar solicitações simples para o servidor Elasticsearch para consultar um ou vários índices e tipos de mapeamento ao mesmo tempo, mas quero criar algo mais útil e mais próximo de um cenário real. Portanto, vou dividir meu projeto em três componentes diferentes. O primeiro componente, que já apresentei, é Elasticsearch, que está disponível via http://localhost:9200/. O segundo componente é uma API que vou criar usando a tecnologia Web API 2. O último componente é um aplicativo de console que usarei para configurar meus índices em Elasticsearch, bem como para fornecer-lhe dados.

Para criar meu novo projeto de Web API 2, primeiro preciso criar um projeto de aplicativo ASP.NET Web e, em seguida, no Console do Gerenciador de Pacotes, execute o seguinte comando de instalação:

Install-Package Microsoft.AspNet.WebApi

Depois de o projeto ser criado, a próxima etapa é adicionar um novo controlador, que usarei para processar solicitações de consulta do cliente e passá-las para Elasticsearch. Adicionar um novo controlador nomeado DiscoveryController envolve nada mais que adicionar um novo item, uma classe Web API ApiController (v2.1). E preciso implementar uma função Search, que será exposta por meio da URL: http://website/api/discovery/search?searchTerm=user_input:

[RoutePrefix("api/discovery")]
public class DiscoveryController : ApiController
{
  [HttpGet]
  [ActionName("search")]
  public IHttpActionResult Search(string searchTerm)
  {
    var discoveryRepository = new DiscoveryRepository();
    var result = discoveryRepository.Search(searchTerm);
    return this.Ok(result);
  }
}

Se o mecanismo Web API 2 não puder serializar uma resposta devido a um loop auto-referenciado, terá de adicionar o seguinte ao arquivo WebApiConfig.cs, que está na pasta AppStart:

GlobalConfiguration.Configuration
.Formatters
.JsonFormatter
.SerializerSettings
.ReferenceLoopHandling =
      ReferenceLoopHandling.Ignore;

Como a Figura 6 mostra, no corpo do controlador que criei, instanciei uma classe do tipo DiscoveryRepository, que é um invólucro em torno do tipo ElasticClient da biblioteca NEST. Dentro deste repositório não genérico, somente leitura implementei dois tipos de funções de pesquisa e ambas devolvem um tipo dinâmico. Esta parte é importante, pois fazendo isto nos corpos de ambas as funções, não estou limitando minhas consultas somente a um índice; ao invés, estou consultando todos os índices e todos os tipos ao mesmo tempo. Isso significa que meus resultados terão uma estrutura diferente (serão de tipos diferentes). A única diferença entre as funções é o método de consulta. Na primeira função somente uso um método QueryString (bit.ly/1mQEEg7), que é uma pesquisa de correspondência exata, e na segunda, um método Fuzzy (bit.ly/1uCk7Ba), que executa uma pesquisa difusa entre índices.

Figura 6 Implementação de dois tipos de pesquisa

namespace ElasticSearchRepository
{
  using System;
  using System.Collections.Generic;
  using System.Linq;
  public class DiscoveryRepository : BaseRepository
  {
    public DiscoveryRepository(Uri elastiSearchServerUrl = null)
      : base(elastiSearchServerUrl)
    {
    }
    ///<summary>  
    public List<Tuple<string, string>> SearchAll(string queryTerm)
    {
      var queryResult=this.client.Search<dynamic>(d =>
        d.AllIndices()
        .AllTypes()
        .QueryString(queryTerm));
      return queryResult
        .Hits
        .Select(c => new Tuple<string, string>(
          c.Indexc.Source.Name.Value))
        .Distinct()
        .ToList();
     }
     ///<summary>  
     public dynamic FuzzySearch(string queryTerm)
     {
       return this.client.Search<dynamic>(d =>
         d.AllIndices()
         .AllTypes()
         .Query(q => q.Fuzzy(f =>
           f.Value(queryTerm))));
     }
  }
}

Agora quando minha API estiver pronta, posso executar e começar a testá-la simplesmente enviando solicitações GET para http://website:port/api/discovery/search?searchTerm=user_input e passar entrada de usuário como o valor do parâmetro de consulta searchTerm. Portanto, a Figura 7 mostra os resultados que minha API gera para o termo de pesquisa “scrum”. Como eu realcei na captura de tela, uma função de pesquisa executou uma consulta sobre todos os índices nos armazenamentos de dados e devolveu ocorrências de múltiplos índices ao mesmo tempo.

Resultados de pesquisa da API para o termo “scrum”
Figura 7 Resultados de pesquisa da API para o termo “scrum”

Ao implementar a camada da API que criei a possibilidade de implementar múltiplos clientes (como um site ou aplicativo móvel), que poderão consumi-la. Isso fornece a habilidade de proporcionar a funcionalidade de pesquisa empresarial aos usuários finais. É possível encontrar uma implementação de exemplo do controle de preenchimento automático para um cliente Web baseado em ASP.NET MVC 4 em meu blog em bit.ly/1yThHiZ.

Conclusão

Big Data deu muito ao mercado da tecnologia, em termos de oportunidades e desafios. Um dos desafios, que também é potencialmente uma ótima oportunidade, é a possibilidade de implementar a pesquisa rápida em petabytes de dados sem precisar saber o local exato dos dados no universo de dados. Neste artigo descrevi como implementar a pesquisa empresarial e demonstrei como fazê-lo no .NET Framework em combinação Elasticsearch e as bibliotecas NEST.


Damian Zapart é um líder de desenvolvimento na Citigroup Inc. e foca-se principalmente em soluções empresariais. Ao mesmo tempo, ele é um geek em programação interessado em tecnologias de ponta, padrões de design e Big Data. Visite seu blog em bit.ly/1suoKN0 para ler mais sobre ele.

Agradecemos aos seguintes especialistas técnicos pela revisão deste artigo: Evren Onem (D&B) e Bruno Terkaly (Microsoft)
Evren Onem (D&B) é um engenheiro de software principal na D&B. Seu trabalho é projetar e criar APIs REST massivamente escalonáveis. Ele também é um pesquisador noturno de redes cognitivas ad hoc de rádio.

Bruno Terkaly é um engenheiro de software principal na Microsoft com o objetivo de permitir o desenvolvimento de aplicativos e serviços líderes do setor entre dispositivos. Ele é responsável por conduzir a nuvem superior e oportunidades móveis nos Estados Unidos e além de uma perspectiva de ativação da tecnologia. Ele ajuda os parceiros a trazer os seus aplicativos para o mercado, fornecendo orientação de arquitetura e compromisso técnico profundo durante a avaliação, desenvolvimento e implantação do ISV. Ele também trabalha junto com grupos de nuvem e engenharia móvel, fornecendo comentários e influenciando o roteiro.