• [+] expand all

Default JSON Result Format

The default JSON result format is used when presentation.format is unset or set to json. Results are rendered with one or more objects:

  • root: mandatory object with the tree of returned data
  • timing: optional object with query timing information
  • trace: optional object for metadata about query execution

Refer to the query API guide for result and tracing examples.

All object names are literal strings, the node root is the map key "root" in the return JSON object, in other words, only strings are used as map keys.

Element Parent Mandatory Type Description

root

root yes Map of string to object The root of the tree of returned data.
children root no Array of objects Array of JSON objects with the same structure as root.
fields root no Map of string to object
summaryfeatures fields no String

Refer to summary-features and observing values used in ranking.

matchfeatures fields no String

Refer to match-features and example use.

totalCount fields no Integer Number of hits.
coverage root no Map of string to string and number Metadata about how much of the total corpus has been scanned to return the given documents.
coverage coverage yes Integer Percentage of total corpus scanned.
documents coverage yes Long The number of documents scanned.
full coverage yes Boolean Whether the full corpus was scanned.
nodes coverage yes Integer The number of search instances used executing the query.
results coverage yes Integer The number of results merged creating the final rendered result.
resultsFull coverage yes Integer The number of full result sets merged.
degraded coverage no Map of string to object Indicator of match-phase degradation.
match-phase degraded no Boolean Indicator whether match-phase degradation has occurred.
timeout degraded no Boolean Indicator whether the query timed out before completion.
adaptive-timeout degraded no Boolean Indicator whether the query timed out with adaptive timeout before completion.
non-ideal-state degraded no Boolean Indicator whether the content cluster is in ideal state.
errors root no Array of objects

Array of error messages with the fields given below. Example.

code errors yes Integer Numeric identifier used by the container application. See error codes and ErrorMessage.java for a short description.
message errors no String Full description.
source errors no String Which data provider logged the error condition.
stackTrace errors no String Stack trace if an exception was involved.
summary errors yes String Short description.
transient errors no Boolean Whether the system is expected to recover from the faulty state on its own. If the flag is not present, this may or may not be the case, or the flag is not applicable.
fields root no Map of string to object
id root no String String or URI identifying the hit, document or other data type. The content of this field is not guaranteed to be meaningful, it is only used as a unique hit identifier for the current result set - refer to #22132 for details.
label root no String The label of a grouping list.
limits root no Object Used in grouping, the limits of a bucket in histogram style data.
from limits no String Lower bound of a bucket group.
to limits no String Upper bound of a bucket group.
relevance root yes Double Double value representing the rank score.
source root no String Which data provider created this node.
types root no Array of string Metadata about what kind of document or other kind of node in the result set this object is.
value root no String Used in grouping for value groups, the argument for the grouping data which is in the fields.

timing

timing no Map of string to object Query timing information, enabled by presentation.timing.
querytime timing no Double Query execution time, in seconds.
summaryfetchtime timing no Double Document summary fetch time, in seconds.
searchtime timing no Double

trace

trace no Map of string to object Metadata about query execution.
children trace no Array of object Array of maps with exactly the same structure as trace itself.
timestamp children no Long Number of milliseconds since the start of query execution this node was added to the trace.
message children no String Descriptive text regarding this step of query execution.
message children no Array of objects
start_time message no String Timestamp, e.g. 2022-07-27 09:51:21.938 UTC
traces message or threads no Array of traces or objects
distribution-key message no Integer The distribution key of the content node creating this span.
duration_ms message no float duration of span
timestamp_ms traces no float time since start of parent, see start_time.
event traces no String Description of span
tag traces no String Name of span
threads traces no Array of objects Array of object that again has traces elements.

JSON Schema

Formal schema for the query API default result format:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "Result",
    "description": "Schema for Vespa results",
    "type": "object",


    "properties": {
        "root": {
            "type": "document_node",
            "required": true
        },
        "trace": {
            "type": "trace_node",
            "required": false
        }
    },

    "definitions": {
        "document_node": {
            "properties": {
                "children": {
                    "type": "array",
                    "items": {
                        "type": "document_node"
                    },
                    "required": false
                },
                "coverage": {
                    "type": "coverage",
                    "required": false
                },
                "errors": {
                    "type": "array",
                    "items": {
                        "type": "error"
                    },
                    "required": false
                },
                "fields": {
                    "type": "object",
                    "additionalProperties": true,
                    "required": false
                },
                "id": {
                    "type": "string",
                    "required": false
                },
                "relevance": {
                    "type": "number",
                    "required": true
                },
                "types": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    },
                    "required": false
                },
                "source": {
                    "type": "string",
                    "required": false
                },
                "value": {
                    "type": "string",
                    "required": false
                },
                "limits": {
                    "type": "object",
                    "required": false
                },
                "label": {
                    "type": "string",
                    "required": false
                }
            },
            "additionalProperties": true,
        },
        "trace_node": {
            "properties": {
                "children": {
                    "type": "array",
                    "items": {
                        "type": "trace_node"
                    },
                    "required": false
                },
                "timestamp": {
                    "type": "number",
                    "required": false
                },
                "message": {
                    "type": "string",
                    "required": false
                }
            }
        },
        "fields": {
            "properties": {
                "totalCount": {
                    "type": "number",
                    "required": true
                }
            }
        },
        "coverage": {
            "properties": {
                "coverage": {
                    "type": "number",
                    "required": true
                },
                "documents": {
                    "type": "number",
                    "required": true
                },
                "full": {
                    "type": "boolean",
                    "required": true
                },
                "nodes": {
                    "type": "number",
                    "required": true
                },
                "results": {
                    "type": "number",
                    "required": true
                },
                "resultsFull": {
                    "type": "number",
                    "required": true
                }
            }
        },
        "error": {
            "properties": {
                "code": {
                    "type": "number",
                    "required": true
                },
                "message": {
                    "type": "string",
                    "required": false
                },
                "source": {
                    "type": "string",
                    "required": false
                },
                "stackTrace": {
                    "type": "string",
                    "required": false
                },
                "summary": {
                    "type": "string",
                    "required": true
                },
                "transient": {
                    "type": "boolean",
                    "required": false
                }
            }
        }
    }
}

Appendix: Legacy Vespa 7 JSON rendering

There were some inconsistencies between search results and document rendering in Vespa 7, which are fixed in Vespa 8. This appendix describes the old behavior, what the changes are, and how to configure to select a specific rendering.

Inconsistent weightedset rendering

Fields with various weightedset types has a JSON input representation (for feeding) as a JSON object; for example {"one":1, "two":2,"three":3} for the value of a a weightedset<string> field. The same format is used when rendering a document (for example when visiting).

In search results however, there are intermediate processing steps during which the field value is represented as an array of item/weight pairs, so in a search result the field value would render as [ {"item":"one", "weight":1}, {"item":"two", "weight":2}, {"item":"three", "weight":3} ]

In Vespa 8, the default JSON renderer for search results outputs the same format as document rendering. If you have code that depends on the old format you can turn off this by setting renderer.json.jsonWsets=false in the query (usually via a query profile).

Inconsistent map rendering

Fields with various map types has a JSON input representation (for feeding) as a JSON object; for example {"1001":1.0, "1002":2.0, "1003":3.0} for the value of a a map<int,float> field. The same format is used when rendering a document (for example when visiting).

In search results however, there are intermediate processing steps and the field value is represented as an array of key/value pairs, so in a search results the field value would (in some cases) render as [ {"key":1001, "value":1.0}, {"key":1002, "value":2.0}, {"key":1003, "value":3.0} ]

In Vespa 8, the default JSON renderer for search results output the same format as document rendering. For code that depends on the old format one can turn off this by setting renderer.json.jsonMaps=false in the query (usually via a query profile).

Geo position rendering

Fields with the type position would in Vespa 7 be rendered using the internal fields "x" and "y". These are integers representing microdegrees, aka geographical degrees times 1 million, of longitude (for x) and latitude (for y). Also, any field foo of type position would trigger addition of two extra synthetic summary fields foo.position and foo.distance (see below for details).

In Vespa 8, positions are rendered with two JSON fields "lat" and "lng", both having a floating-point value. The "lat" field is latitude (going from -90.0 at the South Pole to +90.0 at the North Pole). The "lng" field is longitude (going from -180.0 at the dateline seen as extreme west, via 0.0 at the Greenwich meridian, to +180.0 at the dateline again, now as extreme east). The field names are chosen so the format is the same as used in the Google "places" API.

It's possible to switch back to the legacy (Vespa 7) rendering for geo positions. Set the flag to true by adding the following below the root services element in services.xml:

<legacy>
    <v7-geo-positions>true</v7-geo-positions>
</legacy>

Note that this flag affects rendering both in documents fetched/visited, and in search results; but both the new and old formats are accepted as feed input.

A closely related change is the removal of two synthetic summary fields which would be returned in search results. For example with this in schema:

field mainloc type position {
    indexing: attribute | summary
}

Vespa 7 would include the mainloc summary field, but also mainloc.position and mainloc.distance; the latter only when the query actually had a position to take the distance from.

The first of these (mainloc.position in this case) was mainly useful for producing XML output in older Vespa versions, and now contains just the same information as the mainloc summary field. The second (mainloc.distance in this case) would return a distance in internal units, and can be replaced by a summary feature - here distance(mainloc) would give the same number, while distance(mainloc).km would be the recommended replacement with suitable code changes.

Summary-features wrapped in "rankingExpression"

In Vespa 7, if a rank profile wanted a function foobar returned in summary-features (or match-features), it would be rendered as rankingExpression(foobar) in the output.

For programmatic use, the FeatureData class has extra checking to allow lookup with getDouble("foobar") or getTensor("foobar"), but now it's present and rendered with just the original name as specified.

If applications needs the JSON rendering to look exactly as in Vespa 7, one can specify that in the rank profile. For example, with this in the schema:

rank-profile whatever {
    function lengthScore() { expression: matchCount(title)/fieldLength(title) }
    summary-features {
        matchCount(title)
        lengthScore
        ...

could, in Vespa 7, yield JSON output containing:

    summaryfeatures: {
        matchCount(title): 1,
        rankingExpression(lengthScore): 0.25,
        ...

in Vespa 8, you instead get the expected:

    summaryfeatures: {
        matchCount(title): 1,
        lengthScore: 0.25,
        ...

But to get the old behavior one can specify:

rank-profile whatever {
    function lengthScore() { expression: matchCount(title)/fieldLength(title) }
    summary-features {
        matchCount(title)
			  rankingExpression(lengthScore)
        ...

which gives you the same output as before.