MongoDB – Buscar termo em todos os campos

Ao desenvolver uma API, certamente você se deparou com a missão de ter que fazer uma busca genérica em todos os campos do seu banco.

A primeira vista, essa missão pode assustar, pois, você deve pensar, como eu vou fazer isso? E se eu tiver vários campos, vou ter que especificar tudo na query?

Nesse artigo eu te mostro uma forma bem tranquila de fazer isso e ainda te digo os prós e contras.

O problema

Você está desenvolvendo uma API para o seu aplicativo e quer fazer uma busca “simples”, onde o usuário tem apenas um campo “buscar por…” e ao digitar um termo qualquer, a sua API tem que “se virar” para encontrar os resultados, seja o nome do usuário, idade, sexo, etc. não importa o que o usuário tenha digitado.

Recebendo o termo de busca

Normalmente, em uma API REST você vai receber esse termo pela querystring.

Seria alguma coisa como isso:

GET https://api.seuapp.com.br/v1/endpoint?search=termo

Se você estiver usando express do Node.js para escrever sua API, você vaii obter esse valor da seguinte forma:

app.get('endpoint', (request, response) => {
   const searchTerm = request.query.search;
});

Bacana, agora você já sabe obter o termo para a pesquisa, mas antes de nós fazermos a pesquisa no banco, vou te mostrar o pulo do gato para que isso tudo funcione de uma forma simples.

Criando o índice Text Search

Para resolver esse problema, o MongoDB nos proporciona a funcionalidade Text Search.

O Text Search nada mais é do que um índice múltiplo que quando a gente fizer a busca por ele. Veremos isso em breve.

Para criar esse índice, devemos rodar o seguinte comando no terminal do MongoDB.

db.suacolecao.createIndex( { campo1: "text", campo2: "text" } )

Para acessar o terminal do MongoDB (Mongo Client) você precisa estar com o daemon do banco de dados iniciado e digitar “mongo” no terminal do seu computador.

Pronto! Dessa forma você configurou que quando você fizer sua busca genérica, você vai pesquisar o termo nos campos: “campo1” e “campo2”.

Fique atento!

Digamos que sua coleção tenha 4 campos e você configurou no índice apenas 2 deles, fique atento, pois o termo será procurado apenas nos 2 campos configurados.

Como fazer a query?

Com a confiugração do índice, você “disse” para o MongoDB onde ele deve pesquisar o termo quando for procurado no índice text e para fazer essa busca, você precisa usar esse código.

mongoClient.find({ $text: { $search: searchTerm }});

Bônus: Como melhorar a sua experiência com a busca em índices

É possível que você quera excluir algum termo da busca ou até mesmo pesquisar por um termo exato.

Você pode excluir termos da sua busca, apenas colocando um sinal de menos na frente do termo.

db.suaColecao.find( { $text: { $search: "gol fusca -brasilia" } } )

Essa busca retorna tudo que contenha gol, fusca e que não contenha brasilia.

Você também pode procurar por um termo específico.

db.stores.find( { $text: { $search: "\"brasilia amarela\"" } } )

Esse código vai trazer apenas os resultados que contenham “brasilia amarela”.

Você também pode ordenar os resultados conforme o score da sua busca. O score é uma espécie de pontuação na qual identifica o quanto o termo encontrado é parecido ou igual ao termo pesquisado.

db.suaColecao.find(
   { $text: { $search: "gol fusca puma" } },
   { score: { $meta: "textScore" } }
).sort( { score: { $meta: "textScore" } } )

Outra forma

Existe ainda um outra forma de fazer algo parecido com isso, talvez seja a forma mais comum, entretanto, crio que não é a forma mais performática.

Essa forma não cria um índice específico pra isso, apenas adiciona os valores que devem ser pesquisados em um único campo, exemplo:

db.latasVelhas.insert(
   [
     { _id: 1, name: "Fusca", color: "azul porrada", tags: "Fusca azul porrada" },
     { _id: 2, name: "Bianco", color: "vermelho montana", tags: "Bianco vermelho montana" },
     { _id: 3, name: "Puma", color: "verde", tags: "Puma verde" },
     { _id: 4, name: "Brasilia", color: "amarela", tags: "Brasilia amarela" },
     { _id: 5, name: "Rural", color: "azul e branca", tags: "Rural azul e branca" }
   ]
)

E a busca seria algo como:

db.latasVelhas.find({ tags: /Puma/ });

O que muda nessa coleção é que não temos um índice configurado para fazer o trabalho pra gente, nesse caso a gente faz o trabalho do índice manualmente colocando todos os termos relevantes em um campo dentro da coleção.

Apesar de eu achar que é uma “gambiarra”, funciona! Mas veremos a seguir os prós e contras de ambas as formas.

Prós Vs. Contras

Tudo na vida tem prós e contras e com essa funcionalidade não é diferente.

Se você optar por criar o índice Text Search, a cada vez que houver a necessidade de adicionar um novo campo à busca, você terá que recriar esse índice e isso pode ser bem custoso, entretanto, seu código fica mais limpo, você não precisa escrever nada a mais ao inserir ou editar um dado, isto é, a manutenção é bem menos custosa, fora a velocidade que um índice traz para a sua aplicação.

Se você optar por ter um campo de tags com os termos relevantes, você vai aumentar o tamanho da sua base de forma desnecessária, fora toda a manutenção que esse campo vai exigir quando você inserir, mas principalmente quando precisar editar esses dados. Também sabemos que os índices foram criados para melhorar a performance e nesse caso você não os tem.

Mas nem pense em criar o campo de tags e ainda colocar um índice nele. Essa seria sua pior opção, tendo em vista que a cada modificação você precisara recriar os índices.

Exemplos

Considere a coleção abaixo:

db.latasVelhas.insert(
   [
     { _id: 1, name: "Fusca", color: "azul porrada" },
     { _id: 2, name: "Bianco", color: "vermelho montana" },
     { _id: 3, name: "Puma", color: "verde" },
     { _id: 4, name: "Brasilia", color: "amarela" },
     { _id: 5, name: "Rural", color: "azul e branca" }
   ]
)

Configure o índice Text Search:

db.latasVelhas.createIndex({ name: "text", color: "text" });

Busque por algum termo

db.latasVelhas.find( { $text: { $search: "fusca amarela" } } )

Busque por um termo específico

db.latasVelhas.find( { $text: { $search: "\"Bianco\"" } } )

Referência

Esse artigo foi escrito baseado na documentação do MongoDB que pode ser consultada no link abaixo (em inglês).

https://docs.mongodb.com/manual/text-search/

Licenciamento de Oracle Database: Virtualizar ou não?

Logotipo Oracle

Introdução

Estou liderando um projeto relativamente de grande porte na empresa em que trabalho. O desafio dessa vez é levar o ambiente para um datacenter aqui da cidade (Porto Alegre) ou melhorar as nossas dependências a fim de fornecer a segurança física necessária contra desastres, entretanto, havia a cerca de 3 anos outro projeto parado que o assunto era a criação de uma “nuvem privada”, somei os projetos e estou por aqui ficando quase de cabelo branco… (hehe).

No decorrer desse projeto, me deparei com a seguinte situação, virtualizar ou não virtualizar a minha instância de banco de dados?

No nosso caso utilizamos o Oracle como banco de dados principal na empresa. Nele temos nosso ERP, GED e CRM, além dele temos outros bancos de dados menores para outras tarefas, como intranet por exemplo, mas vamos nos ater ao Oracle.

Quando pensei em virtualizar, logo fui consultar o EULA da Oracle (como de praxe) para ver como ficariam as licenças para esse servidor. Entre diversos EULA’s, conversas com amigos, consultores, fornecedores e DBA’s, pude juntar as informações que forneço para vocês abaixo.

Importante: Não se baseie somente nessas informações, eu não trabalho para a Oracle, não sou certificado Oracle (ainda hehe) e essas informações servem somente como conhecimento e não como documento. Fiquem atentos as versões dos EULA’s fornecidos diretamente no site da fabricante do software. Não me responsabilizo por qualquer ação tomada com base nesse artigo.

Particionamento de servidor

A Oracle considera duas formas de “particionar” um servidor, são elas: soft partition e hard partition.

Abaixo algumas considerações sobre ambas.

Soft Partition

Soft partition é quando fazemos o particionamento em um hypervisor (VMWare, Citrix XenServer, Microsoft Hyper-V, etc). Quando configuramos a VM com um processador apenas.

Essa modalidade NÃO É ACEITA para o cálculo de número de processadores para aquisição de licenças Oracle.

Obs.: caso a virtualização seja feita sob o hypervisor da Oracle, o Oracle VM, existe outro documento permitindo contabilizar somente o processador da VM para licenciamento.

Hard Partition

Hard partition é quando conseguimos realmente especificar o hardware que será utilizado pelo sistema operacional. Essa modalidade sim é aceita pela Oracle como cálculo de numero de processadores para aquisição de licenças Oracle.

Entretanto, nas arquiteturas Intel x86 e x86_64 não são possíveis fazer hard partition, os SO’s não são preparados para isso, somente em arquiteturas RISC, como é o caso de Power (PPC) da IBM por exemplo.

Dessa forma é possível “informar” para o SO quanto de recurso físico ele vai utilizar, independentemente da máquina possuir no total dois processadores, por exemplo.

Licenças Oracle Database Standard Edition One e Oracle Database Standard Edition

A Oracle possui muitas outras licenças e formas de licenciamento, entretanto vou comentar apenas essas duas licenças de processador, as quais eu estudei para a implementação desse projeto.

Obs.: essas licenças podem ser pagas anualmente ou na forma perpétua.

Obs. 1: o valor do suporte anual é de 20% do valor das licenças, é preciso pagar para quantidade total de processadores que você tem e é muito importante que você tenha o suporte atualizado, caso contrário não terá direito de baixar pacotes de atualização do seu software e não terá suporte pela Oracle quando for necessário (geralmente quando chega a esse ponto é porque a coisa está muito, mas muito feia…). Outro motivo é que você paga retroativo, caso pule um ano, por exemplo (isso pode onerar o orçamento do seu departamento de TI e seu gestor certamente não vai gostar).

Considerações sobre Oracle Database Stanadard Edition One

Nessa edição, podemos licenciar equipamentos com até 2 processadores físicos. FIQUEM ATENTOS ENTRETANTO, que mesmo que a licença permita que sejam licenciados até dois processadores, não significa que uma máquina com dois processadores necessitará apenas de uma licença, pelo contrário, significa que caso tenha mais do que 2 processadores, deverá ser usada outro tipo de licença, falaremos disso mais adiante.

Além disso, esse licenciamento custa o equivalente a metade do valor da versão Standard (em 2013) e não possui direitos de uso de Oracle RAC (Real Application Cluster – Consiste basicamente em um conjunto de serviços de alta disponibilidade).

Exemplificando:

Exemplo 1: Um servidor com dois processadores físicos deverá utilizar duas licenças Oracle Database Standard Edition One.

Exemplo 2: Um servidor com quatro processadores físicos deverá utilizar outro tipo de licenciamento.

Exemplo 3: Um servidor com mais de quatro processarores físicos deverá utilizar um tipo de licenciamento diferente do comentado no Exemplo 2 (esse não será comentado nesse artigo).

Considerações sobre Oracle Database Stanadard Edition

Nessa versão, podemos utilizar em equipamentos com até 4 processadores físicos e o mesmo comentado na versão anterior vale para cá.

Essa versão é bem cara e contempla a utilização do Oracle RAC.

Obs.: Ainda existe a versão Enterprise para equipamentos com mais de 4 processadores, que possui um algoritmo de cálculo baseado no total dos cores dos processadores físicos multiplicado por 0,5, mas não vou comentar nada além disso nesse artigo, pois não estudei muito a fundo… além disso, dependendo do tamanho da empresa (quantidade de usuários, se está virtualizado ou não, falaremos mais adiante).

 

Considerações sobre utilização de virtualização

 

As formas de licenciamento supracitadas servem tanto para ambientes virtuais como físicos, entretanto devemos observar alguns pontos além dos já citados em ambientes virtuais. São eles:

Suporte

No projeto inicial iríamos virtualizar a instância de banco de dados sob o Microsoft Windows Server 2012 Hyper-V, entretanto um ponto levantado foi fortemente considerado. A Oracle “não presta suporte” á ambientes que não estão virtualizados com Oracle VM (até então). Na verdade, eles não vão deixar de te atender, mas vão te mandar simular o erro que está ocorrendo em uma máquina física (caso o erro ainda não esteja relatado), aí já viu que a dor de cabeça vira enxaqueca rapidinho…

Utilização de V-motion

Todos os hypervisors tem a possibilidade de v-motion (mover máquinas virtuais dentro de um grupo [pool] de servidores) que é uma ferramenta de excelente aplicabilidade em qualquer ambiente, principalmente quando utilizado com HA (High Available, alta disponibilidade).

Com a utilização desse serviço, a sua VM com a instância Oracle passará por diversos equipamentos e a política da Oracle é clara quanto à isso: toda a máquina que rodar o produto deverá ser licenciada. Portanto, se você tem um pool com 4 máquinas físicas por onde essa VM poderá passar por V-motion, você terá que licenciar todas as máquinas do pool.

Oracle VM

Conforme já citado, a Oracle tem um documento específico para o licenciamento sob Oracle VM, nesse caso é contato apenas o processador da máquina virtual em que está instalado o banco de dados.

Obs.: até então o Oracle VM não faz motion de storage, entretanto, isso não é um impecílio, o próprio storage tem tecnologia suficiente para suprir essa necessidade.

Conclusão

Conforme o estudo realizado sob as licenças Oracle, tive que alterar parte considerável do escopo do projeto inicial, inclusive os custos do projeto.

No meu caso, optei por não virtualizar, apenas utilizar uma máquina (host) específica para esse serviço, mas cada ambiente é um organismo e precisa ser avaliado de perto.

Essas são algumas considerações que eu tive para o meu projeto, mas não tome como documento, pergunte e informe-se em fontes garantidas, como o site da fabricante.

Você também pode contribuir para a comunidade. Tem alguma sugestão ou correção? Descreva nos comentários.

 

E você o que usou ou usaria em seu ambiente?