A partir da versão 2.0, o servidor Couchbase oferece uma maneira eficiente de criar índices para documentos JSON por meio do conceito de exibições.

Usando exibições, é possível definir índices primários, índices compostos e agregações que permitem:

. consultar documentos em diferentes propriedades JSON

. criar estatísticas e agregados

As visualizações geram índices materializados, o que proporciona uma maneira rápida e eficiente de executar consultas predefinidas.

Este blog fornece um exemplo simples de como uma exibição usando map and reduce pode ser criada para indexar um atributo de documento JSON e também para determinar a classificação do documento com base nesse atributo.

O uso de map and reduce é uma maneira muito rápida e eficiente de determinar a classificação e pode ser dimensionado para milhões de usuários, além de fornecer uma pesquisa de classificação muito rápida. Agradecimentos Aarão por ter me ensinado isso!

Isso pode ser usado, por exemplo, para classificar os usuários com base na pontuação ou na experiência.

Este blog ilustra esse conceito para um documento de usuário com dois atributos: nome e experiência, indexa esse documento com base na experiência e permite determinar a classificação com base no atributo experiência.


Primeiro, escreveremos algum código Java que permita a conexão com o servidor Couchbase e a criação de documentos de usuário. O código Java a seguir é autônomo e criará os usuários.

Ele está aproveitando as bibliotecas de código Gson do Google para criar objetos JSON.

 

blog do pacote;

import com.couchbase.client.CouchbaseClient;

import com.couchbase.client.CouchbaseConnectionFactoryBuilder;

import com.google.gson.Gson;

importar java.io.IOException;

importar java.io.UnsupportedEncodingException;

importar java.net.URI;

importar java.util.ArrayList;

classe UserDoc {

   Nome da cadeia de caracteres;

   longa experiência;

   UserDoc(String name, long experience) {

       this.name = name;

       this.experience = experience;

   }

}

/**

*

* @author alexis

*/

classe pública RankView {

   cliente CouchbaseClient estático privado;

   public static void main(String[] args) throws UnsupportedEncodingException, IOException {

       ArrayList nós = nova ArrayList<>();

       // Adicione um ou mais nós de seu cluster (troque o IP pelo seu)

       nodes.add(URI.create("http://127.0.0.1:8091/pools"));

       // Tentativa de conexão com o cliente

       CouchbaseConnectionFactoryBuilder cfb = new CouchbaseConnectionFactoryBuilder();

       cfb.setOpTimeout(10000);

       cfb.setReadBufferSize(1024);

       cfb.setShouldOptimize(true);

       cfb.setTimeoutExceptionThreshold(100);

       tente {

           cliente = novo CouchbaseClient(cfb.buildCouchbaseConnection(nodes, "default", ""));

       } catch (Exception e) {

           System.err.println("Erro ao conectar-se ao Couchbase: " + e.getMessage());

           System.exit(1);

       }

       UserDoc user = null;

       // Cria usuários

       for (int i = 0; i < 10; i++) {

           user = new UserDoc("User" + i, Math.round(Math.random()*1000));

           Gson json = new Gson();

           String jsonString = json.toJson(user);

           client.set(user.name, 0, jsonString);

       }

       cliente.shutdown();

   }

}

Depois de executar esse programa (altere o URL ou o nome do bucket conforme apropriado), você deverá ter 10 usuários em seu bucket.

 

A próxima etapa é um documento de design do usuário com uma visualização de classificação.

A primeira etapa é criar um mapa simples para a exibição de classificação que emitirá o atributo de experiência:

function (doc, meta) {

 Se (doc.experience)

  emit(doc.experience, null);

}

Isso criará um índice com base no atributo de experiência, mas não permitirá determinar a classificação.

É aqui que a adição de um Reduce se encaixa. Adicionaremos o _count reduce incorporado simples.

A visualização completa deve ter a seguinte aparência:

A função Reduce permite agregar o número de documentos do usuário com um valor de experiência conhecido (se doc.experience).

Sem especificar nenhum parâmetro de consulta, o resultado será 10, que é o número de documentos que criamos.

Para consultar a classificação de um usuário específico, o que precisamos fazer é primeiro consultar a classificação de um determinado usuário (User5 neste exemplo):

       // Procurar um usuário específico

       String jsonString = (String) client.get("User5");

       user = json.fromJson(jsonString, UserDoc.class);

A partir daí, podemos criar uma consulta que filtrará essa contagem com uma consulta de intervalo com uma ordem decrescente que começará pelo valor máximo para capturar todos os usuários que têm uma experiência maior e terminará com o valor para o usuário:

       View view = client.getView("User", "Rank");

       Consulta = new Query();

       query.setIncludeDocs(true).setLimit(10000);

       query.setRangeStart(Long.toString(Long.MAX_VALUE));

       query.setRangeEnd(Long.toString(user.experience));

       query.setDescending(true);

       query.setReduce(true);

Dessa forma, a redução produzirá o número de usuários que têm uma experiência melhor do que a experiência desse usuário. A classificação é simplesmente esse número + 1.

       ViewResponse response = client.query(view, query);

       Iterador itr = response.iterator();

       enquanto (itr.hasNext()) {

           ViewRow row = itr.next();

           System.out.println("Rank: " + Long.parseLong(row.getValue()) + 1 );

       }

Isso produzirá o Rank com base na experiência desse usuário, como, por exemplo, o Rank de um usuário:

Classificação: 7

O código Java completo (mais uma vez autônomo) é:

blog do pacote;

import com.couchbase.client.CouchbaseClient;

import com.couchbase.client.CouchbaseConnectionFactoryBuilder;

import com.couchbase.client.protocol.views.Query;

importar com.couchbase.client.protocol.views.View;

import com.couchbase.client.protocol.views.ViewResponse;

import com.couchbase.client.protocol.views.ViewRow;

import com.google.gson.Gson;

importar java.io.IOException;

importar java.io.UnsupportedEncodingException;

importar java.net.URI;

importar java.util.ArrayList;

importar java.util.Iterator;

classe UserDoc {

   Nome da cadeia de caracteres;

   longa experiência;

   UserDoc(String name, long experience) {

       this.name = name;

       this.experience = experience;

   }

}

/**

*

* @author alexis

*/

classe pública RankView {

   cliente CouchbaseClient estático privado;

   public static void main(String[] args) throws UnsupportedEncodingException, IOException {

       ArrayList nós = nova ArrayList<>();

       // Adicione um ou mais nós de seu cluster (troque o IP pelo seu)

       nodes.add(URI.create("http://127.0.0.1:8091/pools"));

       // Tentativa de conexão com o cliente

       CouchbaseConnectionFactoryBuilder cfb = new CouchbaseConnectionFactoryBuilder();

       cfb.setOpTimeout(10000);

       cfb.setReadBufferSize(1024);

       cfb.setShouldOptimize(true);

       cfb.setTimeoutExceptionThreshold(100);

       tente {

           cliente = novo CouchbaseClient(cfb.buildCouchbaseConnection(nodes, "default", ""));

       } catch (Exception e) {

           System.err.println("Erro ao conectar-se ao Couchbase: " + e.getMessage());

           System.exit(1);

       }

       UserDoc user = null;

       Gson json = null;

       // Cria usuários

       for (int i = 0; i < 10; i++) {

           user = new UserDoc("User" + i, Math.round(Math.random() * 1000));

           json = new Gson();

           String jsonString = json.toJson(user);

           client.set(user.name, 0, jsonString);

       }

       // Procurar um usuário específico

       String jsonString = (String) client.get("User5");

       user = json.fromJson(jsonString, UserDoc.class);

       View view = client.getView("User", "Rank");

       Consulta = new Query();

       query.setIncludeDocs(true).setLimit(10000);

       query.setRangeStart(Long.toString(Long.MAX_VALUE));

       query.setRangeEnd(Long.toString(user.experience));

       query.setDescending(true);

       query.setReduce(true);

       ViewResponse response = client.query(view, query);

       Iterador itr = response.iterator();

       enquanto (itr.hasNext()) {

           ViewRow row = itr.next();

           System.out.println("Rank: " + Long.parseLong(row.getValue()) + 1 );

       }

       cliente.shutdown();

   }

}

O uso de uma visualização de mapa e redução para classificação permite procurar uma classificação de forma rápida e muito eficiente sem precisar fazer processamento adicional no lado do cliente.

Para saber mais sobre exibições e consultas no Couchbase, leia: http://www.couchbase.com/docs/couchbase-devguide-2.1.0/indexing-querying-data.html

Para perguntas e comentários: alexis@couchbase.com ou @alexisroos no Twitter.

Autor

Postado por Alexis Roos

Alexis Roos é gerente sênior de engenharia na Salesforce. Alexis tem mais de 20 anos de experiência em engenharia de software, sendo que os últimos cinco anos foram dedicados à ciência e engenharia de dados em larga escala, trabalhando para SIs na Europa, Sun Microsystems/Oracle e várias startups, incluindo Radius Intelligence, Concurrent e Couchbase.

4 Comentários

  1. Gostaria de saber qual é a sintaxe da biblioteca C que corresponde a \'setIncludeDocs\' em java.

  2. Uma visão geral do armazenamento de dados de jogos no couchbase: http://www.couchbase.com/work

  3. Se várias pessoas estiverem na mesma classificação, por exemplo, as classificações 1, 2 e 3 tiverem uma pontuação de 100, a classificação delas sempre será a terceira. Não tenho certeza de como corrigir isso.

    1. Para retornar jogadores com valores user.experience correspondentes como a classificação mais alta em vez da mais baixa, usei a solução alternativa de consultar (user.experience+1) e, em seguida, adicionar 1 à classificação derivada. Parece ter funcionado.

Deixar uma resposta