2 Full Text Search
Anton Nesterov edited this page 2026-02-22 22:54:39 +01:00

Full Text Search

This doc is about full-text search capabilities. For vector similarity search and semantic search, see the Vector Embeddings documentation.

Full-Text Search

Full-Text Search allows you to search text content efficiently.

Enabling FTS

Create a collection with FTS support:

await client.settings.collections.create({
  name: "articles",
  type: "base",
  fields: [
    { name: "title", type: "text", required: true },
    { name: "content", type: "text", required: true },
    { name: "tags", type: "json" },
  ],
  indexes: [
    {
      name: "articles_fts",
      type: "fts",
      fields: ["title", "content"],
    },
  ],
});

Note: The above example shows creating FTS indexes via the indexes property during collection creation. While the search functionality is confirmed to work, the exact mechanism for configuring FTS indexes may need verification with the latest backend implementation.

// Search for articles containing "react"
const results = await client.collection("articles").search("react");

console.log(results);
// [
//   { id: "1", title: "React Tutorial", content: "...", ... },
//   { id: "2", title: "Building React Apps", content: "...", ... },
// ]

Advanced Search Queries

VSKI supports FTS5 query syntax:

// Search for exact phrase
const results = await client.collection("articles").search('"react hooks"');

OR Queries

// Search for articles containing react OR vue
const results = await client.collection("articles").search("react OR vue");

AND Queries

// Search for articles containing both react AND hooks
const results = await client.collection("articles").search("react hooks");

NOT Queries

// Search for articles containing "react" but not "angular"
const results = await client.collection("articles").search("react NOT angular");

Wildcard Searches

// Search for words starting with "react"
const results = await client.collection("articles").search("react*");
// Search for words within 5 words of each other
const results = await client.collection("articles").search(
  '"react hooks" NEAR/5 "components"',
);

Search with Filters

Combine search with regular filters:

const results = await client.collection("articles").getList(1, 20, {
  filter: "published = true",
  search: "react tutorial",
});

Search Options

const results = await client.collection("articles").search("react", {
  fields: ["title", "content"], // Search specific fields
  limit: 10, // Limit results
  expand: "author", // Expand relations
});

Search Result Ranking

Relevance Scoring

FTS provides relevance scores:

const results = await client.collection("articles").search("react");

results.forEach((result) => {
  console.log(`${result.title} - Score: ${result._rank}`);
});

Custom Ranking

Combine search with custom scoring:

const results = await client.collection("articles").getList(1, 20, {
  search: "react",
  sort: "views", // Sort by most viewed
});

Search Suggestions

Implement autocomplete suggestions:

async function getSuggestions(query: string) {
  if (query.length < 2) return [];

  const results = await client.collection("articles").getList(1, 5, {
    search: `${query}*`, // Prefix search
    fields: "title",
  });

  return results.items.map((item) => item.title);
}

Search Analytics

Track search queries for analytics:

async function logSearch(query: string, userId?: string) {
  await client.collection("search_logs").create({
    query,
    userId,
    timestamp: new Date().toISOString(),
    resultsCount: results.items.length,
  });
}

// Usage
const results = await client.collection("articles").search(query);
await logSearch(query, currentUserId);

Performance Optimization

Indexing

Create appropriate indexes for search:

await client.settings.collections.create({
  name: "products",
  type: "base",
  fields: [
    { name: "name", type: "text", required: true },
    { name: "description", type: "text" },
    { name: "category", type: "text" },
  ],
  indexes: [
    {
      name: "products_fts",
      type: "fts",
      fields: ["name", "description"],
    },
    {
      name: "products_category",
      type: "index",
      fields: ["category"],
    },
  ],
});

Caching

Cache search results:

const searchCache = new Map();

async function cachedSearch(query: string) {
  if (searchCache.has(query)) {
    return searchCache.get(query);
  }

  const results = await client.collection("articles").search(query);
  searchCache.set(query, results);

  return results;
}

Debouncing

Debounce search input:

let searchTimeout: number;

function debounceSearch(query: string) {
  clearTimeout(searchTimeout);
  searchTimeout = setTimeout(async () => {
    const results = await client.collection("articles").search(query);
    displayResults(results);
  }, 300);
}

Practical Examples

// Search products with filters
async function searchProducts(
  query: string,
  category?: string,
  minPrice?: number,
) {
  let filter = "published = true";

  if (category) {
    filter += ` && category = '${category}'`;
  }

  if (minPrice) {
    filter += ` && price >= ${minPrice}`;
  }

  return await client.collection("products").getList(1, 20, {
    filter,
    search: query,
    sort: "-popularity",
  });
}
// FAQ search with relevance ranking
async function searchFAQ(query: string) {
  const results = await client.collection("faqs").search(query, {
    fields: ["question", "answer"],
    limit: 5,
  });

  return results;
}

API Endpoints

Method Endpoint Description
GET /api/collections/:name/records/search Full-text search
GET /api/collections/:name/records List with search parameter

Best Practices

  1. Use appropriate indexing - Create FTS indexes for searchable fields
  2. Optimize query syntax - Use specific queries instead of broad ones
  3. Implement pagination - Always use limits with search results
  4. Cache popular searches - Reduce server load
  5. Monitor search performance - Track slow queries
  6. Normalize text - Consistent text formatting improves search