Use um SDK para consultar dados em campos do tipo aninhado de nível único ou multinível. Ao executar uma consulta aninhada, use o recurso de destaque para realçar palavras-chave nos resultados. Para mais informações sobre destaque, consulte destaque.
Os seguintes SDKs do Tablestore suportam consultas aninhadas: Tablestore SDK for Java, Tablestore SDK for Go, Tablestore SDK for Python, Tablestore SDK for Node.js, Tablestore SDK for .NET e Tablestore SDK for PHP. Neste exemplo, utilizamos o Tablestore SDK for Java.
Exemplo de consulta aninhada de nível único
O exemplo a seguir demonstra como consultar dados onde col_nested.nested_1 é igual a tablestore. Neste cenário, col_nested é um campo aninhado cujas linhas filhas contêm as colunas nested_1 e nested_2.
private static void nestedQuery(SyncClient client) {
SearchQuery searchQuery = new SearchQuery();
NestedQuery nestedQuery = new NestedQuery(); // Set the query type to NestedQuery.
nestedQuery.setPath("col_nested"); // Set the path of the nested column.
TermQuery termQuery = new TermQuery(); // Construct the subquery for NestedQuery.
termQuery.setFieldName("col_nested.nested_1"); // Set the column name. Note that it includes the path of the nested column.
termQuery.setTerm(ColumnValue.fromString("tablestore")); // Set the value to query.
nestedQuery.setQuery(termQuery);
nestedQuery.setScoreMode(ScoreMode.None);
searchQuery.setQuery(nestedQuery);
//searchQuery.setGetTotalCount(true); // Set this to return the total number of matched rows.
SearchRequest searchRequest = new SearchRequest("<TABLE_NAME>", "<SEARCH_INDEX_NAME>", searchQuery);
// Use the columnsToGet parameter to specify the columns to return or to return all columns. If you do not set this parameter, only the primary key columns are returned by default.
//SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
//columnsToGet.setReturnAll(true); // Set this to return all columns.
//columnsToGet.setColumns(Arrays.asList("ColName1","ColName2")); // Set this to return specified columns.
//searchRequest.setColumnsToGet(columnsToGet);
SearchResponse resp = client.search(searchRequest);
//System.out.println("TotalCount: " + resp.getTotalCount()); // Print the total number of matched rows, not the number of returned rows.
System.out.println("Row: " + resp.getRows());
}
Exemplo de consulta aninhada multinível
O exemplo a seguir mostra como consultar dados onde col_nested.nested_2.nested_2_2 é igual a tablestore. Aqui, col_nested é um campo aninhado cujas linhas filhas contêm as colunas nested_1 e nested_2. A coluna nested_2 também é um campo aninhado, cujas linhas filhas contêm as colunas nested_2_1 e nested_2_2.
private static void nestedQuery(SyncClient client) {
SearchQuery searchQuery = new SearchQuery();
NestedQuery nestedQuery = new NestedQuery(); // Set the query type to NestedQuery.
nestedQuery.setPath("col_nested.nested_2"); // Set the path of the nested column, which is the parent path of the field to query.
TermQuery termQuery = new TermQuery(); // Construct the subquery for NestedQuery.
termQuery.setFieldName("col_nested.nested_2.nested_2_2"); // Set the column name, which is the full path of the field to query.
termQuery.setTerm(ColumnValue.fromString("tablestore")); // Set the value to query.
nestedQuery.setQuery(termQuery);
nestedQuery.setScoreMode(ScoreMode.None);
searchQuery.setQuery(nestedQuery);
//searchQuery.setGetTotalCount(true); // Set this to return the total number of matched rows.
SearchRequest searchRequest = new SearchRequest("<TABLE_NAME>", "<SEARCH_INDEX_NAME>", searchQuery);
// Use the columnsToGet parameter to specify the columns to return or to return all columns. If you do not set this parameter, only the primary key columns are returned by default.
//SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
//columnsToGet.setReturnAll(true); // Set this to return all columns.
//columnsToGet.setColumns(Arrays.asList("ColName1","ColName2")); // Set this to return specified columns.
//searchRequest.setColumnsToGet(columnsToGet);
SearchResponse resp = client.search(searchRequest);
//System.out.println("TotalCount: " + resp.getTotalCount()); // Print the total number of matched rows, not the number of returned rows.
System.out.println("Row: " + resp.getRows());
}
Exemplo de consulta aninhada composta
Requisitos da consulta
Considere uma tabela de dados com duas colunas: col_string (String) e col_nested (String). A coluna col_nested armazena dados no formato JSON. A tabela abaixo apresenta amostras de dados desta tabela.
Nota
Uma coluna de número de linha foi adicionada a cada linha para fins de demonstração.
|
Número da linha
|
col_string
|
col_nested
|
|
1
|
a
|
[{"col_keyword": "tablestore"},{"col_keyword": "searchindex","col_long": 1}]
|
|
2
|
b
|
[{"col_keyword": "tablestore","col_long": 1}]
|
|
3
|
c
|
[{"col_keyword": "searchindex"},{"col_long": 1}]
|
Suponha que você tenha os seguintes requisitos de consulta para os dados na coluna col_nested:
-
Uma única linha filha atende a múltiplas condições de consulta
Por exemplo, consulte linhas onde uma única linha filha na coluna col_nested atenda simultaneamente a duas condições: o valor da coluna col_keyword é tablestore e o valor da coluna col_long não está vazio.
-
Linhas filhas diferentes atendem a múltiplas condições de consulta
Por exemplo, consulte linhas onde uma linha filha na coluna col_nested tenha o valor tablestore em col_keyword, enquanto outra linha filha possua um valor não vazio em col_long.
Para atender a esses requisitos, siga as etapas abaixo:
-
Crie um índice de busca para a tabela de dados e configure a coluna col_nested como tipo aninhado no índice.
A coluna col_nested contém dois subcampos: col_keyword (Keyword) e col_long (Long).
-
Utilize o método de consulta apropriado conforme sua necessidade.
Para realizar uma consulta onde uma única linha filha satisfaz múltiplas condições, configure múltiplos BoolQueries dentro de um NestedQuery.
Para consultar linhas filhas diferentes que atendem a múltiplas condições, defina múltiplas condições NestedQuery sob um BoolQuery.
Os exemplos a seguir mostram como consultar dados. Consulte o exemplo que corresponde aos seus requisitos de consulta.
Exemplo de consulta onde uma única linha filha atende a múltiplas condições
O exemplo abaixo demonstra como consultar linhas onde uma única linha filha na coluna col_nested atende a ambas as condições: `col_nested.col_keyword é "tablestore" e `col_nested.col_long não está vazio.
Com base nos dados de amostra, apenas os dados da linha 2 atendem às condições da consulta.
public static void nestedQuery(SyncClient client) {
// Condition 1: The value of the col_keyword column in the child row of col_nested must be "tablestore".
TermQuery termQuery = new TermQuery();
termQuery.setFieldName("col_nested.col_keyword");
termQuery.setTerm(ColumnValue.fromString("tablestore"));
// Condition 2: The col_long column in the child row of col_nested must not be empty.
ExistsQuery existsQuery = new ExistsQuery();
existsQuery.setFieldName("col_nested.col_long");
// Use the AND condition of BoolQuery to query for child rows that meet both conditions.
List<Query> mustQueries = new ArrayList<>();
mustQueries.add(termQuery);
mustQueries.add(existsQuery);
BoolQuery boolQuery = new BoolQuery();
boolQuery.setMustQueries(mustQueries);
// Set a BoolQuery within the NestedQuery to require a child row to meet multiple query conditions at the same time.
NestedQuery nestedQuery = new NestedQuery(); // Set the query type to NestedQuery.
nestedQuery.setPath("col_nested"); // Set the path of the nested column, which is the parent path of the field to query.
nestedQuery.setQuery(boolQuery);
nestedQuery.setScoreMode(ScoreMode.None);
SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(nestedQuery);
SearchRequest searchRequest = new SearchRequest("<TABLE_NAME>", "<SEARCH_INDEX_NAME>", searchQuery);
// Use the columnsToGet parameter to specify the columns to return or to return all columns. If you do not set this parameter, only the primary key columns are returned by default.
//SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
//columnsToGet.setReturnAll(true); // Set this to return all columns.
//columnsToGet.setColumns(Arrays.asList("ColName1","ColName2")); // Set this to return specified columns.
//searchRequest.setColumnsToGet(columnsToGet);
SearchResponse resp = client.search(searchRequest);
//System.out.println("TotalCount: " + resp.getTotalCount()); // Print the total number of matched rows, not the number of returned rows.
System.out.println("Row: " + resp.getRows());
}
Exemplo de consulta onde linhas filhas diferentes atendem a múltiplas condições
O exemplo a seguir consulta linhas onde objetos aninhados no campo col_nested atendem a duas condições: col_nested.col_keyword é "tablestore" e col_nested.col_long não está vazio.
Com base nos dados de amostra, os dados da linha 1 e da linha 2 atendem às condições da consulta.
public static void nestedQuery(SyncClient client) {
// Condition 1: The value of the col_keyword column in the child row of col_nested must be "tablestore".
TermQuery termQuery = new TermQuery();
termQuery.setFieldName("col_nested.col_keyword");
termQuery.setTerm(ColumnValue.fromString("tablestore"));
NestedQuery nestedTermQuery = new NestedQuery();
nestedTermQuery.setPath("col_nested");
nestedTermQuery.setScoreMode(ScoreMode.None);
nestedTermQuery.setQuery(termQuery);
// Condition 2: The col_long column in the child row of col_nested must not be empty.
ExistsQuery existsQuery = new ExistsQuery();
existsQuery.setFieldName("col_nested.col_long");
NestedQuery nestedExistsQuery = new NestedQuery();
nestedExistsQuery.setPath("col_nested");
nestedExistsQuery.setScoreMode(ScoreMode.None);
nestedExistsQuery.setQuery(existsQuery);
// Use the AND condition of BoolQuery to query for rows that meet the preceding conditions.
List<Query> mustQueries = new ArrayList<>();
mustQueries.add(nestedTermQuery);
mustQueries.add(nestedExistsQuery);
// The BoolQuery includes multiple NestedQuery conditions. The query is successful if different child rows meet the respective query conditions.
BoolQuery boolQuery = new BoolQuery();
boolQuery.setMustQueries(mustQueries);
SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(boolQuery);
SearchRequest searchRequest = new SearchRequest("<TABLE_NAME>", "<SEARCH_INDEX_NAME>", searchQuery);
// Use the columnsToGet parameter to specify the columns to return or to return all columns. If you do not set this parameter, only the primary key columns are returned by default.
//SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
//columnsToGet.setReturnAll(true); // Set this to return all columns.
//columnsToGet.setColumns(Arrays.asList("ColName1","ColName2")); // Set this to return specified columns.
//searchRequest.setColumnsToGet(columnsToGet);
SearchResponse resp = client.search(searchRequest);
//System.out.println("TotalCount: " + resp.getTotalCount()); // Print the total number of matched rows, not the number of returned rows.
System.out.println("Row: " + resp.getRows());
}
Exemplo de uso de resumo e destaque em uma consulta aninhada
O exemplo a seguir demonstra como usar NestedQuery para consultar dados onde o valor do subcampo Level1_Col1_Nested no campo aninhado Col_Nested corresponde a `hangzhou shanghai`. A consulta de busca é destacada nos resultados retornados.
/**
* Use summary and highlighting in a NestedQuery. Set parameters using innerHits.
*/
public static void nestedQueryWithHighlighting(SyncClient client) {
SearchRequest searchRequest = SearchRequest.newBuilder()
.tableName("<TABLE_NAME>")
.indexName("<SEARCH_INDEX_NAME>")
.returnAllColumnsFromIndex(true)
.searchQuery(SearchQuery.newBuilder()
.limit(5)
.query(QueryBuilders.nested()
.path("Col_Nested")
.scoreMode(ScoreMode.Min)
.query(QueryBuilders.match("Col_Nested.Level1_Col1_Nested", "hangzhou shanghai"))
.innerHits(InnerHits.newBuilder()
.highlight(Highlight.newBuilder()
.addFieldHighlightParam("Col_Nested.Level1_Col1_Nested", HighlightParameter.newBuilder().build())
.build())
.build()))
.build())
.build();
SearchResponse resp = client.search(searchRequest);
// Print the highlighted results.
printSearchHit(resp.getSearchHits(), "");
}
/**
* Print the content of searchHit.
* @param searchHits The search hits.
* @param prefix The prefix to add when printing nested structures to show hierarchical information.
*/
private static void printSearchHit(List<SearchHit> searchHits, String prefix) {
for (SearchHit searchHit : searchHits) {
if (searchHit.getScore() != null) {
System.out.printf("%s Score: %s\n", prefix, searchHit.getScore());
}
if (searchHit.getOffset() != null) {
System.out.printf("%s Offset: %s\n", prefix, searchHit.getOffset());
}
if (searchHit.getRow() != null) {
System.out.printf("%s Row: %s\n", prefix, searchHit.getRow().toString());
}
// Print the highlighted fragments for each field.
if (searchHit.getHighlightResultItem() != null) {
System.out.printf("%s Highlight: \n", prefix);
StringBuilder strBuilder = new StringBuilder();
for (Map.Entry<String, HighlightField> entry : searchHit.getHighlightResultItem().getHighlightFields().entrySet()) {
strBuilder.append(entry.getKey()).append(":").append("[");
strBuilder.append(StringUtils.join(",", entry.getValue().getFragments())).append("]\n");
}
System.out.printf("%s %s", prefix, strBuilder);
}
// Highlighted results for the nested type.
for (SearchInnerHit searchInnerHit : searchHit.getSearchInnerHits().values()) {
System.out.printf("%s Path: %s\n", prefix, searchInnerHit.getPath());
System.out.printf("%s InnerHit: \n", prefix);
printSearchHit(searchInnerHit.getSubSearchHits(), prefix + " ");
}
System.out.println();
}
}
Considere que o campo aninhado multinível Col_Nested inclui dois subcampos: Level1_Col1_Text (Text) e Level1_Col2_Nested (Nested). O campo aninhado Level1_Col2_Nested inclui o subcampo Level2_Col1_Text.
O exemplo a seguir mostra como adicionar um BoolQuery a um NestedQuery para utilizar os recursos de resumo e destaque tanto no subcampo Level1_Col1_Text do campo Col_Nested quanto no subcampo Level2_Col1_Text sob Level1_Col2_Nested.
public static void nestedQueryWithHighlighting(SyncClient client) {
SearchRequest searchRequest = SearchRequest.newBuilder()
.tableName("<TABLE_NAME>")
.indexName("<SEARCH_INDEX_NAME>")
.returnAllColumnsFromIndex(true)
.searchQuery(SearchQuery.newBuilder()
.limit(5)
.query(QueryBuilders.nested()
.path("Col_Nested")
.scoreMode(ScoreMode.Min)
.query(QueryBuilders.bool()
.should(QueryBuilders.match("Col_Nested.Level1_Col1_Text", "hangzhou shanghai"))
.should(QueryBuilders.nested()
.path("Col_Nested.Level1_Col2_Nested")
.scoreMode(ScoreMode.Min)
.query(QueryBuilders.match("Col_Nested.Level1_Col2_Nested.Level2_Col1_Text", "hangzhou shanghai"))
.innerHits(InnerHits.newBuilder()
.highlight(Highlight.newBuilder()
.addFieldHighlightParam("Col_Nested.Level1_Col2_Nested.Level2_Col1_Text", HighlightParameter.newBuilder().build())
.build())
.build())))
.innerHits(InnerHits.newBuilder()
.sort(new Sort(Arrays.asList(
new ScoreSort(),
new DocSort()
)))
.highlight(Highlight.newBuilder()
.addFieldHighlightParam("Col_Nested.Level1_Col1_Text", HighlightParameter.newBuilder().build())
.build())
.build()))
.build())
.build();
SearchResponse resp = client.search(searchRequest);
// Print the highlighted results.
printSearchHit(resp.getSearchHits(), "");
}
/**
* Print the content of searchHit.
* @param searchHits The search hits.
* @param prefix The prefix to add when printing nested structures to show hierarchical information.
*/
private static void printSearchHit(List<SearchHit> searchHits, String prefix) {
for (SearchHit searchHit : searchHits) {
if (searchHit.getScore() != null) {
System.out.printf("%s Score: %s\n", prefix, searchHit.getScore());
}
if (searchHit.getOffset() != null) {
System.out.printf("%s Offset: %s\n", prefix, searchHit.getOffset());
}
if (searchHit.getRow() != null) {
System.out.printf("%s Row: %s\n", prefix, searchHit.getRow().toString());
}
// Print the highlighted fragments for each field.
if (searchHit.getHighlightResultItem() != null) {
System.out.printf("%s Highlight: \n", prefix);
StringBuilder strBuilder = new StringBuilder();
for (Map.Entry<String, HighlightField> entry : searchHit.getHighlightResultItem().getHighlightFields().entrySet()) {
strBuilder.append(entry.getKey()).append(":").append("[");
strBuilder.append(StringUtils.join(",", entry.getValue().getFragments())).append("]\n");
}
System.out.printf("%s %s", prefix, strBuilder);
}
// Highlighted results for the nested type.
for (SearchInnerHit searchInnerHit : searchHit.getSearchInnerHits().values()) {
System.out.printf("%s Path: %s\n", prefix, searchInnerHit.getPath());
System.out.printf("%s InnerHit: \n", prefix);
printSearchHit(searchInnerHit.getSubSearchHits(), prefix + " ");
}
System.out.println();
}
}