IBM Cloud Docs
Criando expressões do seletor

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"
}
Quando especificar o tipo de campo
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 tipo text puderem satisfazer um seletor, o índice json 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 tipo text existem no mesmo campo (por exemplo, fieldone).
    • O seletor pode ser satisfeito apenas usando um índice do tipo text.

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"
}