# Query API

 

Use the Vespa Query API to query, rank and organize data. Example:

```
$ vespa query "select * from music where year > 2001" \
  "ranking=rank_albums" \
  "input.query(user_profile)={{cat:pop}:0.8,{cat:rock}:0.2,{cat:jazz}:0.1}"
```

Simplified, a query has the following components:

- Input data
- Ranking and grouping specification
- Results
- Other execution parameters

This guide is an introduction to the more important elements in the API - refer to the [Query API reference](../reference/api/query.html) for details. See [query execution](#query-execution) below for data flow.

## Input

Input data is both structured data and unstructured text:

```
$ vespa query "select * from music where artist contains \"coldplay\" and default contains text(@q)" \
  "q=head"
```

The first line is the [YQL](query-language.html) query string, that has both structured input (artist=coldplay) and a reference to unstructured user input. The user input is then given in the second line in the _q_ parameter.

Separating the structured data from the unstructured reliefs the application code from interpreting and sanitizing the input data - it is essentially a blob. Vespa can then use heuristics to deduct the user's intention. User input can also be expressed in the [simple query language](../reference/querying/simple-query-language.html) using the [userQuery](../reference/querying/yql.html#userquery) operator.

Finally, input data can also be ranking query features - here the query feature is called _user\_profile_:

```
$ vespa query "select * from music where artist contains \"coldplay\" and default contains text(@q)" \
  "q=head" \
  "ranking=rank_albums" \
  "input.query(user_profile)={{cat:pop}:0.8,{cat:rock}:0.2,{cat:jazz}:0.1}"
```

See [query execution](#query-execution) below.

### Input examples

```
$ vespa query "select * from sources * where default contains text(@animal)" \
  "animal=panda"
```

The text() operator will access the query property "animal", and tokenize the property value into a [weakAnd](../reference/querying/yql.html#grammar) query, resulting in:

`
select * from sources * where weakAnd(default contains "panda")
`

* * *

Changing the value of "animal" without changing the rest of the expression:

```
$ vespa query "select * from sources * where default contains text(@animal)" \
  "animal=panda smokey"
```

The result is:

`
select * from sources * where weakAnd(default contains "panda", default contains "smokey")
`

* * *

Combining multiple query properties, and having a more complex expression:

```
$ vespa query "select * from sources * where range(year, 1963, 2014) and (default contains text(@animal) or default contains text(@teddy))" \
  "animal=panda" \
  "teddy=bear roosevelt"
```

The resulting YQL expression is:

`
select * from sources * where range(year, 1963, 2014) and (weakAnd(default contains "panda") or weakAnd(default contains "bear", default contains "roosevelt"))
`

### Fieldset

Use a fieldset to query multiple fields in the `where` clause. In the schema:

```
fieldset text_content {
    fields: title, description
}
```

Query both fields using the fieldset:

```
$ vespa query 'select * from sources where text_content contains text(@q)' \
  'q=query a fieldset'
```

Fields in the fields set must have the same match modes - read more in the [reference](../reference/schemas/schemas.html#fieldset).

### Query Profiles

Use a [query profile](../reference/api/query.html#queryprofile) to store query parameters in configuration. This makes query strings shorter, and makes it easy to modify queries by modifying configuration only. Use cases are setting query properties for different markets, parameters that do not change, and so on. Query profiles can be nested, versioned and use inheritance.

### Geo Filter and Ranking

Filter by position using latitude and longitude to implement [geo search](geo-search.html). [DistanceToPath](../reference/ranking/rank-features.html#distanceToPath(name).distance) is a [rank function](../basics/ranking.html) based on closeness. Using ranking can often improve results instead of geo filtering.

### Parameter substitution

Parameter substitution lets you provide query values as request parameters instead of inserting this into the YQL string itself. This simplifies query generation, separating the value of the string/set/array from the YQL string - i.e. the value will not corrupt the YQL string if it contains YQL-like syntax:

- Simplify query generation, separating the value of the set/array from the YQL string. 
- Speed up query parsing. Using parameter substitution accelerates string parsing.
- Reduce duplication.

In its simplest form, use [text()](../reference/querying/yql.html#text) for strings:

```
... where default contains text(@user_input)&user_input=free+text
```

Lists, maps and arrays can also be used - examples:

```
# Simple example: provide a set for the IN operator
... where id in (@my_set)&my_set=10,20,30

# Same set, but use the set as a block-list (exclude items in the set)
... where !(id in (@my_set))&my_set=10,20,30

# Use a weightedSet operator
... where weightedSet(field, @my_set)&my_set={a:1,b:2}
```

It is also great to eliminate data duplication, from Vespa 8.287 one can use parameter substitution with `embed`:

```
$ vespa query \
  'yql=select id, from product where {targetHits:10}nearestNeighbor(embedding, query_embedding) oruserQuery()' \
  'input.query(query_embedding)=embed(transformer,@query)' \
  'input.query(query_tokens)=embed(tokenizer,@query)' \
  'query=running shoes for kids, white'
```

Note the use of the parameter named [query](../reference/api/query.html#model.querystring) used by the [userQuery()](../reference/querying/yql.html#userquery) operator. Also note the value substituted in the [embed](../rag/embedding.html#embedding-a-query-text) functions.

See the [reference](../reference/querying/yql.html#parameter-substitution) for a complete list of formats.

## Ranking

[Ranking](../basics/ranking.html) specifies the computation of the query and data. It assigns scores to documents, and returns documents ordered by score. A [rank profile](../reference/api/query.html#ranking.profile) is a specification for how to compute a document's score. An application can have multiple rank profiles, to run different computations. Example, a query specifies query categories and a user embedding (from the [tensor user guide](../ranking/tensor-user-guide.html#ranking-with-tensors)):

```
rank-profile product_ranking inherits default {
    inputs {
        query(q_category) tensor<float>(category{})
        query(q_embedding) tensor<float>(x[4])
    }

    function p_sales_score() {
        expression: sum(query(q_category) * attribute(sales_score))
    }

    function p_embedding_score() {
        expression: closeness(field, embedding)
    }

    first-phase {
        expression: p_sales_score() + p_embedding_score()
    }
    match-features: p_sales_score() p_embedding_score()
}
```

```
```
vespa query 'yql=select * from product where {targetHits:1}nearestNeighbor(embedding,q_embedding)' \
  'input.query(q_embedding)=[1,2,3,4]' \
  'input.query(q_category)={"Tablet Keyboard Cases":0.8, "Keyboards":0.3}' \
  'ranking=product_ranking'
```
```

 **Note:** In this example, `input.query(q_embedding)` is short for`ranking.features.query(q_embedding)` - see the [reference](../reference/api/query.html#ranking.features)for tensor formats.

Results can be ordered using [sorting](../reference/querying/sorting-language.html) instead of ranking.

The above rank profile does not do text ranking - there are however such profiles built-in. Text search is described in more detail in [Text Matching](text-matching.html) - find information about normalizing, prefix search and linguistics there.

## Grouping

[Grouping](grouping.html) is a way to group documents in the result set after ranking. Example, return max 3 albums per artist, grouped on year:

```
$ vespa query "select * from music where true limit 0 | all(group(year) each(max(3) each(output(summary())) ) )"
```

Fields used in grouping must be [attributes](../content/attributes.html). The grouping expression is part of the YQL query string, appended at the end.

Applications can group _all_ documents (select all documents in YQL). Using `limit 0` returns grouping results only.

## Results

All fields are returned in results by default. To specify a subset of fields, use [document summaries](document-summaries.html). When searching text, having a static abstract of the document in a field, or using a [dynamic summary](../reference/schemas/schemas.html#summary)can both improve the visual relevance of the search, and cut bandwidth used.

The default output format is [JSON](../reference/querying/default-result-format.html). A binary [CBOR](https://cbor.io/) format is also available via[format=cbor](../reference/api/query.html#presentation.format) - responses are smaller and faster to render, especially for numeric data, and is a drop-in replacement that produces identical results when deserialized. Write a custom [Renderer](../applications/result-renderers.html) to generate results in other formats.

Read more on [request-response](../applications/processing.html) processing - use this to write code to manipulate results.

## Query execution
 ![Query execution - from query to response](/assets/img/query-to-response.svg)

Phases:

1. **Query processing**: Normalizations, rewriting and enriching. Custom logic in search chains
2. **Matching, ranking and grouping/aggregation:** This phase dispatches the query to content nodes
3. **Result processing, rendering:** Content fetching and snippeting of the top global hits found in the query phase

The above is a simplification - if the query also specifies [result grouping](grouping.html), the query phase might involve multiple phases or round-trips between the container and content nodes. See [life of a query](../performance/sizing-search.html#life-of-a-query-in-vespa) for a deeper dive into query execution details.

Use [trace.explainlevel](../reference/api/query.html#trace.explainlevel) to analyze the query plan. Use these hints to modify the query plan:

- Use [ranked: false](../reference/querying/yql.html#ranked) query annotations to speed up evaluation 
- Use [capped range search](../reference/querying/yql.html#numeric) to efficiently implement top-k selection for ranking a subset of the documents in the index. 

### Query processing and dispatch

1. A query is sent from a front-end application to a container node using the _Query API_ or in any custom request format handled by a custom [request handler](../applications/request-handlers.html), which translates the custom request format to native Vespa APIs. 
2. Query pre-processing, like [linguistic processing](../linguistics/linguistics.html) and [query rewriting](../linguistics/query-rewriting.html), is done in built-in and custom [search chains](../applications/chaining.html) - see [searcher development](../applications/searchers.html). 

3. The query is sent from the container to the _content cluster_ - see [federation](federation.html) for more details. An application can have multiple content clusters - Vespa searches in all by default. [Federation](federation.html) controls how to query the clusters, [sources](../reference/api/query.html#model.sources) names the clusters The illustration above has one content cluster but multiple is fully supported and allows scaling [document types](../basics/schemas.html) differently. E.g. a _tweet_ document type can be indexed in a separate content cluster from a _user_ document type, enabling independent scaling of the two. 

### Matching, ranking, grouping

1. At this point the query enters one or more [content clusters](../reference/applications/services/content.html). In a content cluster with [grouped distribution](../content/elasticity.html#grouped-distribution), the query is dispatched to all content nodes within a single group using a [dispatch policy](../reference/applications/services/content.html#dispatch-tuning), while with a flat single group content cluster the query is dispatched to all content nodes. 
2. The query arrives at the content nodes which performs matching, [ranking](../basics/ranking.html) and aggregation/grouping over the set of documents in the [Ready sub database](../content/proton.html). By default, Vespa uses [DAAT](../performance/feature-tuning.html#hybrid-taat-daat) where the matching and first-phase score calculation is interleaved and not two separate, sequential phases. _vespa-proton_ does matching over the _ready_ documents and [ranks](../basics/ranking.html) as specified with the request/schema. Each content node matches and ranks a subset of the total document corpus and returns the hits along with meta information like total hits and sorting and grouping data, if requested. 

3. Once the content nodes within the group have replied within the [timeout](../performance/graceful-degradation.html), [max-hits / top-k](../reference/applications/services/content.html#dispatch-tuning) results are returned to the container for query phase result processing. In this phase, the only per hit data available is the internal global document id (gid) and the ranking score. There is also result meta information like coverage and total hit count. Additional hit specific data, like the contents of fields, is not available until the result processing phase has completed the content fetching. 

### Result processing (fill) phase

1. When the result from the query phase is available, a custom chained [searcher component](../applications/searchers.html#multiphase-searching) can process the limited data available from the first search phase before contents of the hits is fetched from the content nodes. The fetching from content nodes is lazy and is not invoked before rendering the response, unless asked for earlier by a custom searcher component. 
2. Only fields in the requested [document summaries](document-summaries.html) is fetched from content nodes. The summary request goes directly to the content nodes that produced the result from the query phase. 
3. After the content node requests have completed, the full result set can be processed further by custom components (e.g. doing result deduping, top-k re-ranking), before [rendering](../applications/result-renderers.html) the response. 

## HTTP

 **Note:** Vespa does not provide a java client library for the query API. Best practice for queries is submitting the user-generated query as-is, then use [Searcher components](../applications/searchers.html) to implement additional logic.

The Vespa Team does not recommend any specific HTTP client, since we haven't done any systematic evaluation. We have most experience with the Apache HTTP client. See also [HTTP best practices](https://cloud.vespa.ai/en/http-best-practices) (for Vespa Cloud, but most of it is generally applicable). Also see a discussion in [#24534](https://github.com/vespa-engine/vespa/issues/24534).

Use GET or POST. Parameters can either be sent as GET-parameters or posted as JSON, these are equivalent:

```
$ curl -H "Content-Type: application/json" \
    --data '{"yql" : "select * from sources * where default contains \"coldplay\""}' \
    http://localhost:8080/search/

$ curl http://localhost:8080/search/?yql=select+%2A+from+sources+%2A+where+default+contains+%22coldplay%22
```

### Using POST

The format is based on the [Query API reference](../reference/api/query.html), and has been converted from the _flat_ dot notation to a _nested_ JSON-structure. The request-method must be POST and the _Content-Type_ must be _"application/json"_, e.g.:

```
$ curl -X POST -H "Content-Type: application/json" --data '
  {
      "yql": "select * from sources * where true",
      "offset": 5,
      "ranking": {
          "matchPhase": {
              "ascending": true,
              "maxHits": 15
          }
      },
      "presentation" : {
          "bolding": false,
          "format": "json"
      }
  }' \
  http://localhost:8080/search/
```

 **Note:** Try the[Query Builder](https://github.com/vespa-engine/vespa/tree/master/client/js/app#query-builder)application!

 **Important:** Security filters can block GET and POST requests differently. This can block POSTed queries.

### HTTP

Configure the [http server](../reference/applications/services/http.html#server) - e.g. set _requestHeaderSize_ to configure URL length (including headers):

```
```
<container version="1.0">
    <http>
        <server port="8080" id="myserver">
            <config name="jdisc.http.connector">
                <requestHeaderSize>32768</requestHeaderSize>
            </config>
        </server>
    </http>
</container>
```
```

HTTP keepalive is supported.

Values must be encoded according to standard URL encoding. Thus, space is encoded as +, + as %2b and so on - see [RFC 2396](https://www.ietf.org/rfc/rfc2396.txt).

HTTP status codes are found in the [Query API reference](../reference/api/query.html#http-status-codes). Also see [Stack Overflow question](https://stackoverflow.com/questions/54340386/how-should-i-customize-my-search-result-in-vespa/54344429#54344429).

When implementing a client for the query API, consider the following guidelines for handling HTTP status codes:

#### Client errors vs. server errors

In general clients should only retry requests on _server errors_ (5xx) - not on _client errors_ (4xx). For example, a client should **not** retry a request after receiving a `400 Bad Request` response.

#### Back-pressure handling

Be careful when handling 5xx responses, especially `503 Service Unavailable` and `504 Gateway Timeout`. These responses typically indicate an overloaded system, and blindly retrying without backoff will only worsen the situation. For example, `503 Service Unavailable` is returned whenever there are no available search handler threads to serve the request. This is a clear indication of back-pressure from the system, and clients should reduce overall throughput and implement appropriate throttling mechanisms to avoid exacerbating the overload condition.

## Timeout

See the [reference](../reference/api/query.html#timeout) for how to set the query timeout. Common questions:

- _Does the timeout apply to the whole query or just from when it is sent to the content cluster? If a [Searcher](../applications/searchers.html) goes to sleep in the container for 2\*timeout, will the caller still get a response indicating a timeout?_

- _During multiphase searching, is the query timeout set for each individual searcher, or is the query timeout set for the entire search chain?_

- _If we asynchronously execute several search chains, can we set different query timeouts for each of these chains plus a separate overall timeout for the searcher that performs the asynchronous executions?_

## Error handling

Check for a `root: error` element in the [result](../reference/querying/default-result-format.html#error):

```
```
{
    "root": {
        "errors": [
            {
                "code": 8,
                "summary": "Error in search reply.",
                "source": "music",
                "message": "Could not locate attribute for grouping number 0 : Failed locating attribute vector 'year'. Ignoring this grouping."
            }
        ],
```
```

## Troubleshooting

If Vespa cannot generate a valid search expression from the query string, it will issue the error message _Null query_. To troubleshoot, add [&trace.level=2](../reference/api/query.html#trace.level) to the request. A missing _yql_ parameter will also emit this error message.

### Query tracing

Use _query tracing_ to debug query execution. Enable by using [trace.level=1](../reference/api/query.html#trace.level) (or higher). Add [trace.timestamps=true](../reference/api/query.html#trace.timestamps) for timing info for every searcher invoked. Find a trace example in the result examples below, and try the [practical search performance guide](../performance/practical-search-performance-guide#advanced-query-tracing).

In custom code, use [Query.trace](https://javadoc.io/page/com.yahoo.vespa/container-search/latest/com/yahoo/search/Query.html) to add trace output.

### Large memory usage

Queries that allocate more than 2G RAM will log messages like:

```
mmap 2727 of size 8589934592 from : search::attribute::PostingListMerger<int>::reserveArray(unsigned int, unsigned long)(0x40001513eef0)

(0x400013595334) from (0x400013593acc) from operator new(unsigned long)(0x400013592f88) from search::attribute::PostingListMerger<int>::reserveArray(unsigned int, unsigned long)(0x40001513eef0) from search::attribute::PostingListSearchContextT<int>::fetchPostings(search::queryeval::ExecuteInfo const&, bool)(0x400015159a38) from search::queryeval::SameElementBlueprint::fetchPostings(search::queryeval::ExecuteInfo const&)(0x4000154f36fc) from search::queryeval::IntermediateBlueprint::fetchPostings(search::queryeval::ExecuteInfo const&)(0x40001549ad38) from proton::matching::MatchToolsFactory::MatchToolsFactory(proton::matching::QueryLimiter&, vespalib::Doom const&, proton::matching::ISearchContext&, search::attribute::IAttributeContext&, search::engine::Trace&, std::basic_string_view<char, std::char_traits<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, ...

1 mappings of accumulated size 8589934592
```

This does not necessarily indicate that something is wrong, e.g., range searches use much memory.

## Result examples

A regular query result:

```
```
{
    "root": {
        "id": "toplevel",
        "relevance": 1.0,
        "fields": {
            "totalCount": 1
        },
        "coverage": {
            "coverage": 100,
            "documents": 3,
            "full": true,
            "nodes": 1,
            "results": 1,
            "resultsFull": 1
        },
        "children": [
            {
                "id": "id:mynamespace:music::a-head-full-of-dreams",
                "relevance": 0.16343879032006284,
                "source": "music",
                "fields": {
                    "sddocname": "music",
                    "documentid": "id:mynamespace:music::a-head-full-of-dreams",
                    "artist": "Coldplay",
                    "album": "A Head Full of Dreams",
                    "year": 2015,
                    "category_scores": {
                        "cells": [
                            {
                                "address": {
                                    "cat": "pop"
                                },
                                "value": 1.0
                            },
                            {
                                "address": {
                                    "cat": "rock"
                                },
                                "value": 0.20000000298023224
                            },
                            {
                                "address": {
                                    "cat": "jazz"
                                },
                                "value": 0.0
                            }
                        ]
                    }
                }
            }
        ]
    }
}
```
```

An empty result:

```
```
{
    "root": {
        "fields": {
            "totalCount": 0
        },
        "id": "toplevel",
        "relevance": 1.0
    }
}
```
```

An error result:

```
```
{
    "root": {
        "id": "toplevel",
        "relevance": 1.0,
        "fields": {
            "totalCount": 2
        },
        "coverage": {
            "coverage": 100,
            "documents": 4,
            "full": true,
            "nodes": 2,
            "results": 2,
            "resultsFull": 2
        },
        "errors": [
            {
                "code": 8,
                "summary": "Error in search reply.",
                "source": "music",
                "message": "Could not locate attribute for grouping number 0 : Failed locating attribute vector 'year'. Ignoring this grouping."
            }
        ],
```
```

A simple search application, many undefined fields. Result for the query `/search/?query=blues&hits=3&trace.level=2`

```
```
{

    "trace": {
        "children": [
            {
                "message": "No query profile is used"
            },
            {
                "message": "Invoking chain 'vespa' [com.yahoo.prelude.statistics.StatisticsSearcher@native -&gt; com.yahoo.prelude.querytransform.PhrasingSearcher@vespa -&gt; ... -&gt; federation@native]"
            },
            {
                "children": [
                    {
                        "message": "Detected language: ENGLISH"
                    },
                    {
                        "message": "Language ENGLISH determined by the characters in the terms."
                    },
                    {
                        "message": "Query parsed to: select * from sources * where default contains \"blues\" limit 3"
                    },
                    {
                        "message": "Child execution",
                        "children": [
                            {
                                "message": "Stemming: [select * from sources * where default contains ({\"origin\": {\"original\": \"blues\", \"offset\": 0, \"length\": 5}, \"stem\": false}\"blue\") limit 3]"
                            },
                            {
                                "message": "Lowercasing: [select * from sources * where default contains ({\"origin\": {\"original\": \"blues\", \"offset\": 0, \"length\": 5}, \"stem\": false, \"normalizeCase\": false}\"blue\") limit 3]"
                            },
                            {
                                "message": "sc0.num0 search to dispatch: query=[blue] timeout=5000ms offset=0 hits=3 grouping=0 : collapse=false restrict=[music]"
                            },
                            {
                                "message": "Current state of query tree: WORD[connectedItem=null connectivity=0.0 creator=ORIG explicitSignificance=false fromSegmented=false index=\"\" isRanked=true origin=\"(0 5)\" segmentIndex=0 significance=0.0 stemmed=true uniqueID=1 usePositionData=true weight=100 words=true]{\n \"blue\"\n}\n"
                            },
                            {
                                "message": "YQL+ representation: select * from sources * where default contains ({\"origin\": {\"original\": \"blues\", \"offset\": 0, \"length\": 5}, \"stem\": false, \"normalizeCase\": false, \"id\": 1}\"blue\") limit 3"
                            },
                            {
                                "message": "sc0.num0 dispatch response: Result (3 of total 10 hits)"
                            },
                            {
                                "message": "sc0.num0 fill to dispatch: query=[blue] timeout=5000ms offset=0 hits=3 grouping=0 : collapse=false restrict=[music] summary=[null]"
                            },
                            {
                                "message": "Current state of query tree: WORD[connectedItem=null connectivity=0.0 creator=ORIG explicitSignificance=false fromSegmented=false index=\"\" isRanked=true origin=\"(0 5)\" segmentIndex=0 significance=0.0 stemmed=true uniqueID=1 usePositionData=true weight=100 words=true]{\n \"blue\"\n}\n"
                            },
                            {
                                "message": "YQL+ representation: select * from sources * where default contains ({\"origin\": {\"original\": \"blues\", \"offset\": 0, \"length\": 5}, \"stem\": false, \"normalizeCase\": false, \"id\": 1}\"blue\") limit 3"
                            }
                        ]
                    },
                    {
                        "message": "Child execution"
                    }
                ]
            }
        ]
    },
    "root": {
        "id": "toplevel",
        "relevance": 1,
        "fields": {
            "totalCount": 10
        },
        "coverage": {
            "coverage": 100,
            "documents": 10,
            "full": true,
            "nodes": 1,
            "results": 1,
            "resultsFull": 1
        },
        "children": [
            {
                "id": "index:0/0/0/dfd9fcfa650b44545ef0b8b2",
                "relevance": "-Infinity",
                "source": "basicsearch",
                "fields": {
                    "sddocname": "music",
                    "title": "Electric Blues",
                    "artist": "",
                    "song": "",
                    "bgndata": "",
                    "sales": "NaN",
                    "pto": -1,
                    "mid": 2,
                    "ew": "blues",
                    "surl": "https://shopping.yahoo.com/shop?d=hab&amp;id=1807865261",
                    "userrate": "NaN",
                    "pid": "",
                    "weight": "NaN",
                    "url": "",
                    "isbn": "",
                    "fmt": "",
                    "albumid": "",
                    "disp_song": "",
                    "pfrom": "NaN",
                    "bgnpfrom": "NaN",
                    "categories": "Blues",
                    "data": "",
                    "numreview": "NaN",
                    "bgnsellers": 0,
                    "image": "",
                    "artistspid": "",
                    "newestedition": "NaN",
                    "bgnpto": "",
                    "year": "NaN",
                    "did": "NaN",
                    "scorekey": "NaN",
                    "cbid": "NaN",
                    "summaryfeatures": "",
                    "documentid": "id:test:music::https://shopping.yahoo.com/shop?d=hab&amp;id=1807865261"
                }
            },
            {
                "id": "index:0/0/0/273d384dc214386c934d793f",
                "relevance": "-Infinity",
                "source": "basicsearch",
                "fields": {
                    "sddocname": "music",
                    "title": "Delta Blues",
                    "artist": "",
                    "song": "",
                    "bgndata": "",
                    "sales": "NaN",
                    "pto": -1,
                    "mid": 2,
                    "ew": "blues",
                    "surl": "https://shopping.yahoo.com/shop?d=hab&amp;id=1804905714",
                    "userrate": "NaN",
                    "pid": "",
                    "weight": "NaN",
                    "url": "",
                    "isbn": "",
                    "fmt": "",
                    "albumid": "",
                    "disp_song": "",
                    "pfrom": "NaN",
                    "bgnpfrom": "NaN",
                    "categories": "Blues",
                    "data": "",
                    "numreview": "NaN",
                    "bgnsellers": 0,
                    "image": "",
                    "artistspid": "",
                    "newestedition": "NaN",
                    "bgnpto": "",
                    "year": "NaN",
                    "did": "NaN",
                    "scorekey": "NaN",
                    "cbid": "NaN",
                    "summaryfeatures": "",
                    "documentid": "id:test:music::https://shopping.yahoo.com/shop?d=hab&amp;id=1804905714"
                }
            },
            {
                "id": "index:0/0/0/b3c74a9bf3aea1e2260311c0",
                "relevance": "-Infinity",
                "source": "basicsearch",
                "fields": {
                    "sddocname": "music",
                    "title": "Chicago Blues",
                    "artist": "",
                    "song": "",
                    "bgndata": "",
                    "sales": "NaN",
                    "pto": -1,
                    "mid": 2,
                    "ew": "blues",
                    "surl": "https://shopping.yahoo.com/shop?d=hab&amp;id=1804905710",
                    "userrate": "NaN",
                    "pid": "",
                    "weight": "NaN",
                    "url": "",
                    "isbn": "",
                    "fmt": "",
                    "albumid": "",
                    "disp_song": "",
                    "pfrom": "NaN",
                    "bgnpfrom": "NaN",
                    "categories": "Blues",
                    "data": "",
                    "numreview": "NaN",
                    "bgnsellers": 0,
                    "image": "",
                    "artistspid": "",
                    "newestedition": "NaN",
                    "bgnpto": "",
                    "year": "NaN",
                    "did": "NaN",
                    "scorekey": "NaN",
                    "cbid": "NaN",
                    "summaryfeatures": "",
                    "documentid": "id:test:music::https://shopping.yahoo.com/shop?d=hab&amp;id=1804905710"
                }
            }
        ]
    }
}
```
```

Result for the grouping query `
    /search/?hits=0&yql=select * from sources * where sddocname contains purchase | all(group(customer) each(output(sum(price))))
  `

```
```
{

    "trace": {
        "children": [
            {
                "children": [
                    {
                        "message": "Child execution"
                    }
                ]
            }
        ]
    },
    "root": {
        "id": "toplevel",
        "relevance": 1,
        "fields": {
            "totalCount": 20
        },
        "coverage": {
            "coverage": 100,
            "documents": 20,
            "full": true,
            "nodes": 1,
            "results": 1,
            "resultsFull": 1
        },
        "children": [
            {
                "id": "group:root:0",
                "relevance": 1,
                "continuation": {
                    "this": ""
                },
                "children": [
                    {
                        "id": "grouplist:customer",
                        "relevance": 1,
                        "label": "customer",
                        "children": [
                            {
                                "id": "group:string:Jones",
                                "relevance": 9870,
                                "value": "Jones",
                                "fields": {
                                    "sum(price)": 39816
                                }
                            },
                            {
                                "id": "group:string:Brown",
                                "relevance": 8000,
                                "value": "Brown",
                                "fields": {
                                    "sum(price)": 20537
                                }
                            },
                            {
                                "id": "group:string:Smith",
                                "relevance": 6100,
                                "value": "Smith",
                                "fields": {
                                    "sum(price)": 19484
                                }
                            }
                        ]
                    }
                ]
            }
        ]
    }
}
```
```

 Copyright © 2026 - [Cookie Preferences](#)

### On this page:

- [Query API](#page-title)
- [Input](#input)
- [Input examples](#input-examples)
- [Fieldset](#fieldset)
- [Query Profiles](#query-profiles)
- [Geo Filter and Ranking](#geo-filter-and-ranking)
- [Parameter substitution](#parameter-substitution)
- [Ranking](#ranking)
- [Grouping](#grouping)
- [Results](#results)
- [Query execution](#query-execution)
- [Query processing and dispatch](#query-processing-dispatch)
- [Matching, ranking, grouping](#matching-ranking-grouping)
- [Result processing (fill) phase](#result-processing-fill-phase)
- [HTTP](#http)
- [Using POST](#using-post)
- [HTTP](#jetty)
- [Timeout](#timeout)
- [Error handling](#error-handling)
- [Troubleshooting](#troubleshooting)
- [Query tracing](#query-tracing)
- [Large memory usage](#large-memory-usage)
- [Result examples](#result-examples)

