Node.js e N1QL

Então, recentemente, adicionei suporte ao nosso cliente Node.js para executar consultas N1QL em seu cluster, desde que você esteja executando uma instância do mecanismo N1QL (para obter a versão atualizada do cliente Node.js com esse suporte, aponte o npm para nossa ramificação principal do github em https://github.com/couchbase/couchnode). Quando o implementei, não tinha muito o que testar na época, por isso achei que seria um esforço interessante ver como o exemplo de amostra de cerveja do Node.js ficaria bom se usássemos inteiramente consultas N1QL em vez de exibições.

Primeiro, comecei convertendo as consultas básicas que simplesmente selecionavam todas as cervejas ou cervejarias dos dados de amostra e, em seguida, passei a converter a consulta de pesquisa ao vivo para usar também o N1QL. Pensei em escrever uma pequena postagem no blog sobre as conversões e fazer algumas observações sobre o que notei ao longo do processo.

Aqui está nossa primeira consulta:

var q = {
  limite : ENTRADAS_POR_PÁGINA,
  obsoleto : falso
};
db.visualização( "cerveja", "by_name", q).consulta(função(erro, valores) {
  var chaves = _.arrancar(valores, 'id');
  db.getMulti( chaves, nulo, função(erro, resultados) {
    var cervejas = _.mapa(resultados, função(v, k) {
      v.valor.id = k;
      retorno v.valor;
    });
    res.renderizar('beer/index', {"cervejas:cervejas});
  })
});

e a versão convertida:

db.consulta(
    "SELECT META().id AS id, * FROM beer-sample WHERE type='beer' LIMIT " + ENTRADAS_POR_PÁGINA,
    função(erro, cervejas) {
  res.renderizar('beer/index', {"cervejas:cervejas});
});

Como você pode ver, não precisamos mais fazer duas operações separadas para recuperar a lista. Podemos executar nossa consulta N1QL que retornará todas as informações de que precisamos e as formatará adequadamente; em vez de precisar reformatar os dados e adicionar nossos valores de id, podemos simplesmente selecioná-los como parte do conjunto de resultados. Acho que a versão do N1QL aqui é muito mais concisa e agradeço a simplicidade da construção da consulta.

Em seguida, converti a função de listagem de cervejarias seguindo um caminho semelhante, e aqui está o resultado: como você pode ver, ele é igualmente bonito e conciso:

db.consulta(
    "SELECT META().id AS id, name FROM beer-sample WHERE type='brewery' LIMIT " + ENTRADAS_POR_PÁGINA,
    função(erro, cervejarias) {
  res.renderizar('brewery/index', {"cervejarias:cervejarias});
});

Em seguida, converti os métodos de pesquisa. Esses foram um pouco mais desafiadores, pois olhando diretamente para o código original, sem pensar no que ele estava tentando alcançar, a semântica não era imediatamente óbvia:

var q = { tecla de início : valor,
  chave final : valor + JSON.analisar(‘”u0FFF"'),
  obsoleto : falso,
  limite : ENTRADAS_POR_PÁGINA }
db.visualização( "cerveja", "by_name", q).consulta(função(erro, valores) {
  var chaves = _.arrancar(valores, 'id');
  db.getMulti( chaves, nulo, função(erro, resultados) {
    var cervejas = [];
    para(var k em resultados) {
      cervejas.empurrar({
        'id': k,
        "nome: resultados[k].valor.nome,
        'brewery_id': resultados[k].valor.brewery_id
      });
    }
    res.enviar(cervejas);
  });
});

Novamente, temos um pouco de código para realizar algo que você deve esperar que seja bastante simples. Caso não tenha percebido, a consulta map/reduce acima recupera uma listagem de cervejas cujos nomes começam com o valor inserido pelo usuário. Vamos converter isso em uma cláusula N1QL LIKE e, como bônus adicional, permitiremos que o termo de pesquisa apareça em qualquer lugar da string, em vez de exigi-lo no início:

db.consulta(
    "SELECT META().id, name, brewery_id FROM beer-sample WHERE type='beer' AND LOWER(name) LIKE '%" + prazo + "%' LIMIT " + ENTRADAS_POR_PÁGINA,
    função(erro, cervejas) {
  res.enviar(cervejas);
});

Novamente, reduzimos uma grande quantidade de código vagamente compreensível a uma consulta simples e concisa. Acredito que isso começa a mostrar o poder do N1QL e por que estou tão empolgado em ver o N1QL. No entanto, há uma ressalva que notei ao fazer isso: semelhante ao SQL, você precisa ter cuidado com o tipo de dados do usuário que está passando para as consultas. Escrevi uma função de limpeza simples para tentar evitar qualquer intenção mal-intencionada (embora o N1QL seja atualmente somente leitura de qualquer forma), mas meu código de limpeza não é de forma alguma extenso. Outro problema que notei é que nossa segunda consulta com a cláusula LIKE foi executada muito mais lentamente como uma consulta N1QL do que quando usamos map/reduce. Acredito que isso seja simplesmente o resultado de o N1QL ainda ser uma prévia para desenvolvedores, e ainda há muitas otimizações a serem feitas pela equipe do N1QL.

Se quiser ver o código-fonte totalmente convertido, dê uma olhada na ramificação n1ql do repositório beersample-node disponível aqui, https://github.com/couchbaselabs/beersample-node/tree/n1ql.  

Obrigado! Brett

Compartilhe este artigo
Receba atualizações do blog do Couchbase em sua caixa de entrada
Esse campo é obrigatório.

Autor

Postado por Brett Lawson, engenheiro de software principal, Couchbase

Brett Lawson é engenheiro de software principal da Couchbase. Brett é responsável pelo projeto e desenvolvimento dos clientes Node.js e PHP do Couchbase, além de desempenhar um papel no projeto e desenvolvimento da biblioteca C, libcouchbase.

4 Comentários

  1. Estou muito animado para ver o trabalho sobre isso

  2. Temo que os exemplos que usam a concatenação de strings para criar essas consultas levem as pessoas a vulnerabilidades \"n1ql-injection\". Na verdade, provavelmente seria mais seguro (e talvez funcione dessa forma, ainda não verifiquei) permitir a substituição de variáveis na consulta (por exemplo, \"%d\" ou \"$1\" ou algo assim), para que você possa garantir que os valores sejam escapados.

    1. Olá, Justin,
      Concordo plenamente com você e, em uma versão posterior, introduzimos a parametrização e a substituição incorporadas (embora isso não esteja disponível no momento para o SDK 2.0). Esperamos criar uma solução elegante para isso em breve. Definitivamente, antes que o N1QL seja GA! Obrigado pela contribuição!
      Abraços, Brett

Deixe um comentário

Pronto para começar a usar o Couchbase Capella?

Iniciar a construção

Confira nosso portal do desenvolvedor para explorar o NoSQL, procurar recursos e começar a usar os tutoriais.

Use o Capella gratuitamente

Comece a trabalhar com o Couchbase em apenas alguns cliques. O Capella DBaaS é a maneira mais fácil e rápida de começar.

Entre em contato

Deseja saber mais sobre as ofertas do Couchbase? Deixe-nos ajudar.