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
// 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
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
// 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
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.
Gostaria de saber qual é a sintaxe da biblioteca C que corresponde a \'setIncludeDocs\' em java.
Uma visão geral do armazenamento de dados de jogos no couchbase: http://www.couchbase.com/work…
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.
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.