Criando expressões do seletor
Em geral, sempre que você tem um operador que usa um argumento, esse argumento em si pode ser outro operador com argumentos próprios. Essa expansão permite expressões de seletor mais complexas.
Os operadores lógicos de combinação ou de matriz, como $regex
, podem levar a uma varredura integral do banco de dados quando você usa índices do tipo JSON, resultando em um desempenho ruim. Apenas operadores de igualdade, tais como
$eq
,
$gt
, $gte
, $lt
e $lte
(mas não $ne
), habilitam consultas de índice. Para assegurar que os índices sejam usados efetivamente, analise o plano de explicação para cada consulta.
A maioria das expressões de seletor funciona exatamente como esperado para o operador. Os algoritmos de correspondência usados pelo operador $regex
são atualmente baseados na na bibliotecaPerl Compatible Regular Expression(PCRE). No entanto, nem toda a biblioteca PCRE é implementada. Além disso, algumas partes do operador $regex
vão além do que a PCRE oferece. Para obter
mais informações sobre o que é implementado, consulte as informações sobre Expressão regular de Erlang.
Sintaxe de classificação
O campo sort
contém uma lista de pares de nome de campo e de direção, expressa como uma matriz básica. O primeiro par de nome de campo e de direção é o nível mais alto de classificação. Pares adicionais, se fornecidos, especifique
o próximo nível de classificação.
O campo de classificação pode ser qualquer campo. Use notação de ponto se for necessário para subcampos.
O valor de direção é asc
para crescente e desc
para decrescente.
Se você excluir o valor de direção, o padrão asc
será usado.
Veja o exemplo a seguir de sintaxe de classificação simples:
[
{
"fieldName1": "desc"
},
{
"fieldName2": "desc"
}
]
Veja o exemplo a seguir de classificação simples, assumindo a direção padrão de "crescente" para ambos os campos:
[
"fieldNameA", "fieldNameB"
]
Um requisito típico é procurar algum conteúdo usando um seletor e depois classificar os resultados de acordo com o campo especificado na direção preferencial.
Para usar classificação, um índice contendo os campos de classificação deve ser definido. Se estiver usando o índice json
, os campos deverão ser especificados na mesma ordem da classificação.
Atualmente, o IBM Cloudant Query não suporta vários campos com ordens de classificação diferentes, portanto, a direção deve ser todos crescentes ou todos decrescentes.
Se a direção for crescente, será possível usar uma sequência em vez de um objeto para especificar os campos de classificação.
Para nomes de campos em consultas de classificação em um índice text
em que o tipo do campo que está sendo classificado não pode ser determinado, pode ser necessário que um tipo de campo seja especificado. Por exemplo:
{
"<fieldname>:string": "asc"
}
Qual índice é usado pela consulta? | Requisito de tipo de campo |
---|---|
Índice JSON | Nenhum |
Índice de texto de todos os campos em todos os documentos | Especifique o campo de classificação na consulta se o banco de dados contiver documentos nos quais o campo de classificação tem um tipo. Além disso, especifique o campo de classificação na consulta se ele contiver documentos nos quais o campo de classificação tem um tipo diferente. |
Qualquer outro índice de texto | Especifique o tipo de todos os campos de classificação na consulta. |
Um índice de texto de todos os campos em todos os documentos é criado quando se usa a sintaxe:
"index": {}
.
A ordem de classificação é indefinida quando os campos contêm tipos de dados diferentes. Essa característica é uma diferença importante entre índices de texto e visualização. O comportamento de classificação para campos com tipos de dados diferentes pode mudar em versões futuras.
Veja o exemplo a seguir de uma consulta simples que usa a classificação:
{
"selector": {
"Actor_name": "Robert De Niro"
},
"sort": [
{
"Actor_name": "asc"
},
{
"Movie_runtime": "asc"
}
]
}
Campos de filtragem
É possível especificar exatamente quais campos são retornados para um documento quando você seleciona por meio de um banco de dados. As duas vantagens são mostradas na lista a seguir:
- Seus resultados são limitados apenas àquelas partes do documento que são necessárias para o seu aplicativo.
- Uma redução no tamanho da resposta.
Os campos a serem retornados são especificados como uma matriz.
Apenas os campos de filtro especificados estão incluídos na resposta. _id
ou outros campos de metadados não são incluídos automaticamente.
Veja o exemplo a seguir de recuperação seletiva de campos por meio de documentos correspondentes:
{
"selector": {
"Actor_name": "Robert De Niro"
},
"fields": [
"Actor_name",
"Movie_year",
"_id",
"_rev"
]
}
Paginação
O IBM Cloudant Query suporta paginação por campo de marcador. Cada resposta _find
contém um marcador - um token que o IBM Cloudant usa para determinar de onde retomar quando forem feitas consultas posteriores. Para obter o próximo
conjunto de resultados da consulta, inclua o marcador que foi recebido na resposta anterior para sua próxima solicitação. Lembre-se de manter o mesmo seletor, caso contrário, você receberá resultados inesperados. Para paginação retroativa,
é possível usar um marcador anterior para retornar o conjunto anterior de resultados.
A presença de um marcador não garante mais resultados. É possível testar se você está no final do conjunto de resultados comparando o número de resultados retornados com o tamanho da página solicitada. Se os resultados retornados forem menores que o limite, nenhum outro resultado terá sido retornado no conjunto de resultados.
Planos de explicação
O IBM Cloudant Query escolhe qual índice usar para responder a uma consulta, a menos que você especifique um índice no tempo de consulta.
Quando você especifica um índice a usar, O IBM Cloudant Query usa a lógica a seguir:
- O planejador de consulta observa a seção do seletor e localiza o índice com a correspondência mais próxima de operadores e campos que são usados na consulta. Se dois ou mais índices do tipo JSON corresponderem, o índice com o menor número de campos no índice será o preferencial. Se dois ou mais índices candidatos ainda existirem, o índice com o primeiro nome alfabético será escolhido.
- Se tanto um índice de tipo
json
quanto um índice de tipotext
puderem satisfazer um seletor, o índicejson
será escolhido por padrão. - O índice de tipo
text
é escolhido quando as condições a seguir são atendidas:- Um índice de tipo
json
e um índice de tipotext
existem no mesmo campo (por exemplo,fieldone
). - O seletor pode ser satisfeito apenas usando um índice do tipo
text
.
- Um índice de tipo
Por exemplo, suponha que você tenha um índice de tipo text
e um índice de tipo json
para o campo foo
e queira usar um seletor semelhante à amostra a seguir:
{
"foo": {
"$in": ["red","blue","green"]
}
}
O IBM Cloudant Query usa o índice de tipo text
porque um índice de tipo json
não pode satisfazer o seletor.
No entanto, é possível usar um seletor diferente com os mesmos índices:
{
"foo": {
"$gt": 2
}
}
Neste exemplo, O IBM Cloudant Query usa o índice do tipo json
porque ambos os tipos de índices podem satisfazer o seletor.
Para identificar qual índice está sendo usado por uma consulta específica, envie um POST
para o terminal _explain
para o banco de dados com a consulta como dados. Os detalhes do índice em uso são mostrados no objeto
index
dentro do resultado.
Veja o exemplo a seguir que usa HTTP para mostrar como identificar o índice que foi usado para responder a uma consulta:
POST /movies/_explain HTTP/1.1
Host: $SERVICE_URL
Content-Type: application/json
{
"selector": {
"$text": "Pacino",
"year": 2010
}
}
Veja o exemplo a seguir que usa a linha de comandos para mostrar como identificar o índice que foi usado para responder a uma consulta:
curl "$SERVICE_URL/movies/_explain" \
-X POST \
-H "Content-Type: application/json" \
-d '{
"selector": {
"$text": "Pacino",
"year": 2010
}
}'
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.ExplainResult;
import com.ibm.cloud.cloudant.v1.model.PostExplainOptions;
import java.util.HashMap;
import java.util.Map;
Cloudant service = Cloudant.newInstance();
Map<String, Object> selector = new HashMap<>();
selector.put("$text", "Pacino");
selector.put("year", 2010);
PostExplainOptions explainOptions =
new PostExplainOptions.Builder()
.db("movies")
.selector(selector)
.build();
ExplainResult response =
service.postExplain(explainOptions).execute()
.getResult();
System.out.println(response);
import { CloudantV1 } from '@ibm-cloud/cloudant';
const service = CloudantV1.newInstance({});
let selector: CloudantV1.Selector = {
'$text': 'Pacino',
'year': 2010
};
service.postExplain({
db: 'movies',
selector: selector
}).then(response => {
console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1
service = CloudantV1.new_instance()
response = service.post_find(
db='movies',
selector={'$text': 'Pacino', 'year': 2010}
).get_result()
print(response)
postExplainOptions := service.NewPostExplainOptions(
"movies",
map[string]interface{}{
"$text": "Pacino",
"year": 2010,
},
)
explainResult, _, err := service.PostExplain(postExplainOptions)
if err != nil {
panic(err)
}
b, _ := json.MarshalIndent(explainResult, "", " ")
fmt.Println(string(b))
O exemplo do Go anterior requer o bloco de importação a seguir:
import (
"encoding/json"
"fmt"
"github.com/IBM/cloudant-go-sdk/cloudantv1"
)
Veja a resposta de exemplo a seguir que mostra qual índice foi usado para responder a uma consulta:
{
"dbname": "$ACCOUNT/movies",
"index": {
"ddoc": "_design/32372935e14bed00cc6db4fc9efca0f1537d34a8",
"name": "32372935e14bed00cc6db4fc9efca0f1537d34a8",
"type": "text",
"def": {
"default_analyzer": "keyword",
"default_field": {},
"selector": {},
"fields": []
}
},
"selector": {
"$and": [
{
"$default": {
"$text": "Pacino"
}
},
{
"year": {
"$eq": 2010
}
}
]
},
"opts": {
"use_index": [],
"bookmark": [],
"limit": 10000000000,
"skip": 0,
"sort": {},
"fields": "all_fields",
"r": [
49
],
"conflicts": false
},
"limit": 200,
"skip": 0,
"fields": "all_fields",
"query": "(($default:Pacino) AND (year_3anumber:2010))",
"sort": "relevance"
}
Para instruir uma consulta a usar um índice específico, inclua o parâmetro use_index
na consulta.
O valor do parâmetro use_index
usa um dos formatos a seguir:
"use_index": "$DDOC"
"use_index": ["$DDOC","$INDEX_NAME"]
Veja a consulta de exemplo a seguir com instruções para usar um índice específico:
{
"selector": {
"$text": "Pacino",
"year": 2010
},
"use_index": "_design/32372935e14bed00cc6db4fc9efca0f1537d34a8"
}