Files
genai-toolbox/docs/en/resources/tools/firestore/firestore-query.md
Yuan Teoh 293c1d6889 feat!: update configuration file v2 (#2369)
This PR introduces a significant update to the Toolbox configuration
file format, which is one of the primary **breaking changes** required
for the implementation of the Advanced Control Plane.

# Summary of Changes
The configuration schema has been updated to enforce resource isolation
and facilitate atomic, incremental updates.
* Resource Isolation: Resource definitions are now separated into
individual blocks, using a distinct structure for each resource type
(Source, Tool, Toolset, etc.). This improves readability, management,
and auditing of configuration files.
* Field Name Modification: Internal field names have been modified to
align with declarative methodologies. Specifically, the configuration
now separates kind (general resource type, e.g., Source) from type
(specific implementation, e.g., Postgres).

# User Impact
Existing tools.yaml configuration files are now in an outdated format.
Users must eventually update their files to the new YAML format.

# Mitigation & Compatibility
Backward compatibility is maintained during this transition to ensure no
immediate user action is required for existing files.
* Immediate Backward Compatibility: The source code includes a
pre-processing layer that automatically detects outdated configuration
files (v1 format) and converts them to the new v2 format under the hood.
* [COMING SOON] Migration Support: The new toolbox migrate subcommand
will be introduced to allow users to automatically convert their old
configuration files to the latest format.

# Example
Example for config file v2:
```
kind: sources
name: my-pg-instance
type: cloud-sql-postgres
project: my-project
region: my-region
instance: my-instance
database: my_db
user: my_user
password: my_pass
---
kind: authServices
name: my-google-auth
type: google
clientId: testing-id
---
kind: tools
name: example_tool
type: postgres-sql
source: my-pg-instance
description: some description
statement: SELECT * FROM SQL_STATEMENT;
parameters:
- name: country
  type: string
  description: some description
---
kind: tools
name: example_tool_2
type: postgres-sql
source: my-pg-instance
description: returning the number one
statement: SELECT 1;
---
kind: toolsets
name: example_toolset
tools:
- example_tool
```

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Averi Kitsch <akitsch@google.com>
2026-01-27 16:58:43 -08:00

12 KiB

title, type, weight, description, aliases
title type weight description aliases
firestore-query docs 1 Query a Firestore collection with parameterizable filters and Firestore native JSON value types
/resources/tools/firestore-query

Overview

The firestore-query tool allows you to query Firestore collections with dynamic, parameterizable filters that support Firestore's native JSON value types. This tool is designed for querying single collection, which is the standard pattern in Firestore. The collection path itself can be parameterized, making it flexible for various use cases. This tool is particularly useful when you need to create reusable query templates with parameters that can be substituted at runtime.

Developer Note: This tool serves as the general querying foundation that developers can use to create custom tools with specific query patterns.

Key Features

  • Parameterizable Queries: Use Go template syntax to create dynamic queries
  • Dynamic Collection Paths: The collection path can be parameterized for flexibility
  • Native JSON Value Types: Support for Firestore's typed values (stringValue, integerValue, doubleValue, etc.)
  • Complex Filter Logic: Support for AND/OR logical operators in filters
  • Template Substitution: Dynamic collection paths, filters, and ordering
  • Query Analysis: Optional query performance analysis with explain metrics (non-parameterizable)

Configuration

Basic Configuration

kind: tools
name: query_countries
type: firestore-query
source: my-firestore-source
description: Query countries with dynamic filters
collectionPath: "countries"
filters: |
  {
    "field": "continent",
    "op": "==",
    "value": {"stringValue": "{{.continent}}"}
  }
parameters:
  - name: continent
    type: string
    description: Continent to filter by
    required: true

Advanced Configuration with Complex Filters

kind: tools
name: advanced_query
type: firestore-query
source: my-firestore-source
description: Advanced query with complex filters
collectionPath: "{{.collection}}"
filters: |
  {
    "or": [
      {"field": "status", "op": "==", "value": {"stringValue": "{{.status}}"}},
      {
        "and": [
          {"field": "priority", "op": ">", "value": {"integerValue": "{{.priority}}"}},
          {"field": "area", "op": "<", "value": {"doubleValue": {{.maxArea}}}},
          {"field": "active", "op": "==", "value": {"booleanValue": {{.isActive}}}}
        ]
      }
    ]
  }
select:
  - name
  - status
  - priority
orderBy:
  field: "{{.sortField}}"
  direction: "{{.sortDirection}}"
limit: 100
analyzeQuery: true
parameters:
  - name: collection
    type: string
    description: Collection to query
    required: true
  - name: status
    type: string
    description: Status to filter by
    required: true
  - name: priority
    type: string
    description: Minimum priority value
    required: true
  - name: maxArea
    type: float
    description: Maximum area value
    required: true
  - name: isActive
    type: boolean
    description: Filter by active status
    required: true
  - name: sortField
    type: string
    description: Field to sort by
    required: false
    default: "createdAt"
  - name: sortDirection
    type: string
    description: Sort direction (ASCENDING or DESCENDING)
    required: false
    default: "DESCENDING"

Parameters

Configuration Parameters

Parameter Type Required Description
type string Yes Must be firestore-query
source string Yes Name of the Firestore source to use
description string Yes Description of what this tool does
collectionPath string Yes Path to the collection to query (supports templates)
filters string No JSON string defining query filters (supports templates)
select array No Fields to select from documents(supports templates - string or array)
orderBy object No Ordering configuration with field and direction(supports templates for the value of field or direction)
limit integer No Maximum number of documents to return (default: 100) (supports templates)
analyzeQuery boolean No Whether to analyze query performance (default: false)
parameters array Yes Parameter definitions for template substitution

Runtime Parameters

Runtime parameters are defined in the parameters array and can be used in templates throughout the configuration.

Filter Format

Simple Filter

{
  "field": "age",
  "op": ">",
  "value": {"integerValue": "25"}
}

AND Filter

{
  "and": [
    {"field": "status", "op": "==", "value": {"stringValue": "active"}},
    {"field": "age", "op": ">=", "value": {"integerValue": "18"}}
  ]
}

OR Filter

{
  "or": [
    {"field": "role", "op": "==", "value": {"stringValue": "admin"}},
    {"field": "role", "op": "==", "value": {"stringValue": "moderator"}}
  ]
}

Nested Filters

{
  "or": [
    {"field": "type", "op": "==", "value": {"stringValue": "premium"}},
    {
      "and": [
        {"field": "type", "op": "==", "value": {"stringValue": "standard"}},
        {"field": "credits", "op": ">", "value": {"integerValue": "1000"}}
      ]
    }
  ]
}

Firestore Native Value Types

The tool supports all Firestore native JSON value types:

Type Format Example
String {"stringValue": "text"} {"stringValue": "{{.name}}"}
Integer {"integerValue": "123"} or {"integerValue": 123} {"integerValue": "{{.age}}"} or {"integerValue": {{.age}}}
Double {"doubleValue": 45.67} {"doubleValue": {{.price}}}
Boolean {"booleanValue": true} {"booleanValue": {{.active}}}
Null {"nullValue": null} {"nullValue": null}
Timestamp {"timestampValue": "RFC3339"} {"timestampValue": "{{.date}}"}
GeoPoint {"geoPointValue": {"latitude": 0, "longitude": 0}} See below
Array {"arrayValue": {"values": [...]}} See below
Map {"mapValue": {"fields": {...}}} See below

Complex Type Examples

GeoPoint:

{
  "field": "location",
  "op": "==",
  "value": {
    "geoPointValue": {
      "latitude": 37.7749,
      "longitude": -122.4194
    }
  }
}

Array:

{
  "field": "tags",
  "op": "array-contains",
  "value": {"stringValue": "{{.tag}}"}
}

Supported Operators

  • < - Less than
  • <= - Less than or equal
  • > - Greater than
  • >= - Greater than or equal
  • == - Equal
  • != - Not equal
  • array-contains - Array contains value
  • array-contains-any - Array contains any of the values
  • in - Value is in array
  • not-in - Value is not in array

Examples

Example 1: Query with Dynamic Collection Path

kind: tools
name: user_documents
type: firestore-query
source: my-firestore
description: Query user-specific documents
collectionPath: "users/{{.userId}}/documents"
filters: |
  {
    "field": "type",
    "op": "==",
    "value": {"stringValue": "{{.docType}}"}
  }
parameters:
  - name: userId
    type: string
    description: User ID
    required: true
  - name: docType
    type: string
    description: Document type to filter
    required: true

Example 2: Complex Geographic Query

kind: tools
name: location_search
type: firestore-query
source: my-firestore
description: Search locations by area and population
collectionPath: "cities"
filters: |
  {
    "and": [
      {"field": "country", "op": "==", "value": {"stringValue": "{{.country}}"}},
      {"field": "population", "op": ">", "value": {"integerValue": "{{.minPopulation}}"}},
      {"field": "area", "op": "<", "value": {"doubleValue": {{.maxArea}}}}
    ]
  }
orderBy:
  field: "population"
  direction: "DESCENDING"
limit: 50
parameters:
  - name: country
    type: string
    description: Country code
    required: true
  - name: minPopulation
    type: string
    description: Minimum population (as string for large numbers)
    required: true
  - name: maxArea
    type: float
    description: Maximum area in square kilometers
    required: true

Example 3: Time-based Query with Analysis

kind: tools
name: activity_log
type: firestore-query
source: my-firestore
description: Query activity logs within time range
collectionPath: "logs"
filters: |
  {
    "and": [
      {"field": "timestamp", "op": ">=", "value": {"timestampValue": "{{.startTime}}"}},
      {"field": "timestamp", "op": "<=", "value": {"timestampValue": "{{.endTime}}"}},
      {"field": "severity", "op": "in", "value": {"arrayValue": {"values": [
        {"stringValue": "ERROR"},
        {"stringValue": "CRITICAL"}
      ]}}}
    ]
  }
select:
  - timestamp
  - message
  - severity
  - userId
orderBy:
  field: "timestamp"
  direction: "DESCENDING"
analyzeQuery: true
parameters:
  - name: startTime
    type: string
    description: Start time in RFC3339 format
    required: true
  - name: endTime
    type: string
    description: End time in RFC3339 format
    required: true

Usage

Invoking the Tool

# Using curl
curl -X POST http://localhost:5000/api/tool/your-tool-name/invoke \
  -H "Content-Type: application/json" \
  -d '{
    "continent": "Europe",
    "minPopulation": "1000000",
    "maxArea": 500000.5,
    "isActive": true
  }'

Response Format

Without analyzeQuery:

[
  {
    "id": "doc1",
    "path": "countries/doc1",
    "data": {
      "name": "France",
      "continent": "Europe",
      "population": 67000000,
      "area": 551695
    },
    "createTime": "2024-01-01T00:00:00Z",
    "updateTime": "2024-01-15T10:30:00Z"
  }
]

With analyzeQuery:

{
  "documents": [...],
  "explainMetrics": {
    "planSummary": {
      "indexesUsed": [...]
    },
    "executionStats": {
      "resultsReturned": 10,
      "executionDuration": "15ms",
      "readOperations": 10
    }
  }
}

Best Practices

  1. Use Typed Values: Always use Firestore's native JSON value types for proper type handling
  2. String Numbers for Large Integers: Use string representation for large integers to avoid precision loss
  3. Template Security: Validate all template parameters to prevent injection attacks
  4. Index Optimization: Use analyzeQuery to identify missing indexes
  5. Limit Results: Always set a reasonable limit to prevent excessive data retrieval
  6. Field Selection: Use select to retrieve only necessary fields

Technical Notes

  • Queries operate on a single collection (the standard Firestore pattern)
  • Maximum of 100 filters per query (configurable)
  • Template parameters must be properly escaped in JSON contexts
  • Complex nested queries may require composite indexes

See Also