or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

assets.mdclient.mdentries.mdindex.mdquerying.mdspace-content-types.mdsync.mdtags-taxonomy.md
tile.json

querying.mddocs/

Content Querying

Advanced querying capabilities for filtering, searching, and retrieving specific content with type-safe parameter validation and comprehensive query operators.

Capabilities

Basic Query Parameters

Core query parameters available for most content retrieval operations.

interface BaseQueries {
  /** Limit number of results (max: 1000, default: 100) */
  limit?: number;
  /** Skip entries for pagination (max: 9000) */
  skip?: number;
  /** Order results by field (prefix with - for descending) */
  order?: string;
  /** Specify locale (default: default locale of space) */
  locale?: string;
  /** Select specific fields to return */
  select?: string;
  /** Include linked entries and assets (default: 1, max: 10) */
  include?: number;
}

Search Queries

Full-text search capabilities across content fields.

interface SearchQueries {
  /** Full-text search across all text fields */
  query?: string;
}

Usage Examples:

// Basic full-text search
const searchResults = await client.getEntries({
  query: "JavaScript tutorial"
});

// Search within specific content type
const blogSearchResults = await client.getEntries({
  content_type: "blogPost",
  query: "React hooks"
});

Field Equality Queries

Filter content by exact field values.

interface EqualityQueries {
  /** Filter by exact field value */
  [key: `fields.${string}`]: any;
  /** Filter by system property */
  [key: `sys.${string}`]: any;
}

Usage Examples:

// Filter by field values
const featuredPosts = await client.getEntries({
  content_type: "blogPost",
  "fields.featured": true,
  "fields.category": "Technology"
});

// Filter by system properties
const recentEntries = await client.getEntries({
  "sys.createdAt[gte]": "2023-01-01T00:00:00Z"
});

Existence Queries

Check for the presence or absence of field values.

interface ExistenceQueries {
  /** Check if field exists and has a value */
  [key: `fields.${string}[exists]`]: boolean;
  /** Check if system property exists */
  [key: `sys.${string}[exists]`]: boolean;
}

Usage Examples:

// Find entries with specific fields present
const entriesWithImages = await client.getEntries({
  content_type: "blogPost",
  "fields.featuredImage[exists]": true
});

// Find entries missing certain fields
const drafts = await client.getEntries({
  content_type: "blogPost",
  "fields.publishDate[exists]": false
});

Range Queries

Filter content using range comparisons for numbers and dates.

interface RangeQueries {
  /** Greater than */
  [key: `fields.${string}[gt]`]: string | number;
  /** Greater than or equal */
  [key: `fields.${string}[gte]`]: string | number;
  /** Less than */
  [key: `fields.${string}[lt]`]: string | number;
  /** Less than or equal */
  [key: `fields.${string}[lte]`]: string | number;
  /** System property range queries */
  [key: `sys.${string}[gt]`]: string | number;
  [key: `sys.${string}[gte]`]: string | number;
  [key: `sys.${string}[lt]`]: string | number;
  [key: `sys.${string}[lte]`]: string | number;
}

Usage Examples:

// Date range queries
const recentPosts = await client.getEntries({
  content_type: "blogPost",
  "fields.publishDate[gte]": "2023-01-01",
  "fields.publishDate[lte]": "2023-12-31"
});

// Numeric range queries
const expensiveProducts = await client.getEntries({
  content_type: "product",
  "fields.price[gt]": 100,
  "fields.price[lte]": 1000
});

Set Queries

Filter content using set operations (in/nin).

interface SetQueries {
  /** Field value is in the provided array */
  [key: `fields.${string}[in]`]: string[];
  /** Field value is not in the provided array */
  [key: `fields.${string}[nin]`]: string[];
  /** System property set queries */
  [key: `sys.${string}[in]`]: string[];
  [key: `sys.${string}[nin]`]: string[];
}

Usage Examples:

// Include multiple categories
const techAndDesignPosts = await client.getEntries({
  content_type: "blogPost",
  "fields.category[in]": ["Technology", "Design", "Development"]
});

// Exclude specific content
const nonDraftEntries = await client.getEntries({
  content_type: "blogPost",
  "fields.status[nin]": ["draft", "archived"]
});

Subset Queries

Filter arrays and check for matches within array fields.

interface SubsetQueries {
  /** All array items match the query */
  [key: `fields.${string}[all]`]: string[];
  /** Some array items match the query */
  [key: `fields.${string}[in]`]: string[];
  /** No array items match the query */
  [key: `fields.${string}[nin]`]: string[];
}

Usage Examples:

// Entries with all specified tags
const wellTaggedPosts = await client.getEntries({
  content_type: "blogPost",
  "fields.tags[all]": ["javascript", "tutorial"]
});

// Entries with some of the specified tags
const relatedPosts = await client.getEntries({
  content_type: "blogPost",
  "fields.tags[in]": ["react", "vue", "angular"]
});

Reference Queries

Filter content by linked entries and assets.

interface ReferenceQueries {
  /** Links to specific entry */
  [key: `fields.${string}.sys.id`]: string;
  /** Links to entry of specific content type */
  [key: `fields.${string}.sys.contentType.sys.id`]: string;
  /** Links to any of the specified entries */
  [key: `fields.${string}[in]`]: string[];
  /** Doesn't link to any of the specified entries */
  [key: `fields.${string}[nin]`]: string[];
}

Usage Examples:

// Find entries linked to specific author
const authorPosts = await client.getEntries({
  content_type: "blogPost",
  "fields.author.sys.id": "author-id"
});

// Find entries linked to authors of specific type
const postsWithPersonAuthors = await client.getEntries({
  content_type: "blogPost",
  "fields.author.sys.contentType.sys.id": "person"
});

// Find entries linked to any of several categories
const categorizedPosts = await client.getEntries({
  content_type: "blogPost",
  "fields.category[in]": ["cat1", "cat2", "cat3"]
});

Location Queries

Filter content by geographical proximity (for Location fields).

interface LocationQueries {
  /** Find entries near coordinates */
  [key: `fields.${string}[near]`]: string; // "lat,lon"
  /** Find entries within bounding box */
  [key: `fields.${string}[within]`]: string; // "lat1,lon1,lat2,lon2"
}

Usage Examples:

// Find locations near New York City
const nearbyLocations = await client.getEntries({
  content_type: "venue",
  "fields.location[near]": "40.7128,-74.0060"
});

// Find locations within a bounding box
const locationsInArea = await client.getEntries({
  content_type: "venue",
  "fields.location[within]": "40.7,-74.1,40.8,-73.9"
});

Order Queries

Control result ordering with multiple fields and directions.

interface OrderQueries {
  /** Order by field (prefix with - for descending) */
  order?: string | string[];
}

Usage Examples:

// Order by single field
const orderedPosts = await client.getEntries({
  content_type: "blogPost",
  order: "-fields.publishDate" // Descending
});

// Multiple ordering criteria
const complexOrdered = await client.getEntries({
  content_type: "blogPost",
  order: ["fields.featured", "-fields.publishDate"]
});

// Order by system properties
const byCreation = await client.getEntries({
  order: "-sys.createdAt"
});

Select Queries

Optimize responses by selecting only needed fields.

interface SelectQueries {
  /** Comma-separated list of fields to include */
  select?: string;
}

Usage Examples:

// Select only specific fields
const minimalEntries = await client.getEntries({
  content_type: "blogPost",
  select: "fields.title,fields.slug,sys.id"
});

// Select nested fields
const authorNames = await client.getEntries({
  content_type: "blogPost",
  select: "fields.title,fields.author.fields.name"
});

// Select system fields
const systemInfo = await client.getEntries({
  select: "sys.id,sys.createdAt,sys.updatedAt"
});

Advanced Querying Patterns

Combining Multiple Query Types

// Complex query combining multiple filters
const complexQuery = await client.getEntries({
  content_type: "blogPost",
  query: "JavaScript",                           // Full-text search
  "fields.category": "Technology",               // Exact match
  "fields.publishDate[gte]": "2023-01-01",      // Range query
  "fields.featured": true,                       // Boolean filter
  "fields.tags[in]": ["tutorial", "beginner"],  // Set query
  "fields.author[exists]": true,                 // Existence check
  order: ["-fields.publishDate", "fields.title"], // Multi-field ordering
  limit: 20,                                     // Pagination
  skip: 0,
  include: 2                                     // Include linked content
});

Pagination Patterns

// Implement pagination
async function getAllEntries(contentType: string, batchSize: number = 100) {
  const allEntries = [];
  let skip = 0;
  let hasMore = true;

  while (hasMore) {
    const batch = await client.getEntries({
      content_type: contentType,
      limit: batchSize,
      skip: skip
    });

    allEntries.push(...batch.items);
    skip += batchSize;
    hasMore = batch.items.length === batchSize;
  }

  return allEntries;
}

Dynamic Query Building

// Build queries dynamically
function buildQuery(filters: Record<string, any>): any {
  const query: any = {};

  Object.entries(filters).forEach(([key, value]) => {
    if (value !== undefined && value !== null && value !== '') {
      if (Array.isArray(value)) {
        query[`${key}[in]`] = value;
      } else if (typeof value === 'object' && value.operator) {
        query[`${key}[${value.operator}]`] = value.value;
      } else {
        query[key] = value;
      }
    }
  });

  return query;
}

// Usage
const dynamicQuery = buildQuery({
  content_type: "blogPost",
  "fields.category": "Technology",
  "fields.publishDate": { operator: "gte", value: "2023-01-01" },
  "fields.tags": ["javascript", "tutorial"]
});

const results = await client.getEntries(dynamicQuery);

Query Validation and Error Handling

// Validate query parameters
function validateQuery(query: any): string[] {
  const errors = [];

  if (query.limit && (query.limit < 1 || query.limit > 1000)) {
    errors.push("Limit must be between 1 and 1000");
  }

  if (query.skip && query.skip > 9000) {
    errors.push("Skip cannot exceed 9000");
  }

  if (query.include && (query.include < 0 || query.include > 10)) {
    errors.push("Include must be between 0 and 10");
  }

  return errors;
}

// Use validation
const query = {
  content_type: "blogPost",
  limit: 50,
  include: 2
};

const validationErrors = validateQuery(query);
if (validationErrors.length > 0) {
  console.error("Query validation errors:", validationErrors);
} else {
  const results = await client.getEntries(query);
}