.do
API Reference

Searches API

Search semantically with text queries and vector embeddings

Search semantically with text queries and vector embeddings. Find resources across your business using natural language queries or semantic similarity.

Overview

Business searches provide semantic discovery through:

  • Text-based keyword search
  • Vector similarity search with embeddings
  • Filter and sort capabilities
  • Pagination for large result sets
  • Type-specific searches
import { createBusinessApi } from 'business-as-code'

const api = createBusinessApi({
  apiKey: process.env.APIS_DO_KEY,
})

// Text search
const results = await api.searches.query({
  query: 'enterprise customers in california',
  types: ['Customer'],
  filters: {
    state: 'CA',
    tier: 'enterprise',
  },
})

query()

Perform a text-based search query.

Signature

query(
  query: BusinessQuery
): Promise<BusinessResource[]>

Parameters

ParameterTypeRequiredDescription
queryBusinessQueryYesSearch query object

Query Properties

PropertyTypeRequiredDescription
querystringYesSearch query text
typesstring[]NoResource types to search
filtersobjectNoAdditional filters
sortobjectNoSort order (field and order)
paginationobjectNoPagination settings (page and pageSize)

Returns

Promise that resolves to an array of matching BusinessResource objects.

Example

// Simple text search
const customers = await api.searches.query({
  query: 'acme corporation',
  types: ['Customer'],
})

// Search with filters
const results = await api.searches.query({
  query: 'enterprise plan',
  types: ['Customer', 'Organization'],
  filters: {
    plan: 'enterprise',
    status: 'active',
    'revenue.gt': 100000,
  },
})

// Search with sorting
const recentOrders = await api.searches.query({
  query: 'pending orders',
  types: ['Order'],
  filters: {
    status: 'pending',
  },
  sort: {
    field: 'orderDate',
    order: 'desc',
  },
})

// Paginated search
const page1 = await api.searches.query({
  query: 'customers',
  types: ['Customer'],
  pagination: {
    page: 1,
    pageSize: 25,
  },
})

vector()

Perform vector similarity search using embeddings.

Signature

vector(
  embedding: number[],
  filters?: Record<string, any>
): Promise<BusinessResource[]>

Parameters

ParameterTypeRequiredDescription
embeddingnumber[]YesVector embedding (e.g., from OpenAI)
filtersobjectNoAdditional filters

Returns

Promise that resolves to an array of semantically similar BusinessResource objects.

Example

// Generate embedding (using OpenAI or similar)
const embedding = await generateEmbedding('Looking for customers interested in AI and automation')

// Vector search
const similarCustomers = await api.searches.vector(embedding, {
  types: ['Customer'],
  limit: 10,
})

console.log(`Found ${similarCustomers.length} similar customers`)

Complete Vector Search Example

import { createBusinessApi } from 'business-as-code'
import OpenAI from 'openai'

const api = createBusinessApi({
  apiKey: process.env.APIS_DO_KEY,
})

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
})

// Generate embedding for search query
async function semanticSearch(query: string) {
  // Generate embedding
  const embeddingResponse = await openai.embeddings.create({
    model: 'text-embedding-3-small',
    input: query,
  })

  const embedding = embeddingResponse.data[0].embedding

  // Search with vector
  const results = await api.searches.vector(embedding, {
    types: ['Customer', 'Product', 'Article'],
    limit: 20,
  })

  return results
}

// Use it
const results = await semanticSearch('enterprise customers interested in AI automation tools')

results.forEach((resource) => {
  console.log(`${resource.$type}: ${resource.name}`)
})

Search Examples

Search and filter customers using semantic queries:

// Find customers by name → https://actions.org.ai/find.Customer
const results = await api.searches.query({
  query: 'acme',
  types: ['Customer'],
})

// Find customers by location → https://actions.org.ai/find.Customer
const californiaCustomers = await api.searches.query({
  query: 'california technology companies',
  types: ['Customer', 'Organization'],
  filters: {
    'address.state': 'CA',
    industry: 'Technology',
  },
})

// Find high-value customers → https://actions.org.ai/find.Customer
const enterpriseCustomers = await api.searches.query({
  query: 'enterprise',
  types: ['Customer'],
  filters: {
    tier: 'enterprise',
    'lifetimeValue.gt': 100000,
  },
  sort: {
    field: 'lifetimeValue',
    order: 'desc',
  },
})

Semantic Abstraction: find.Customer

Search products with filters and semantic similarity:

// Find products by name → https://actions.org.ai/find.Product
const laptops = await api.searches.query({
  query: 'laptop',
  types: ['Product'],
  filters: {
    category: 'Electronics',
    availability: 'InStock',
  },
})

// Find products in price range → https://actions.org.ai/find.Product
const affordableProducts = await api.searches.query({
  query: 'office equipment',
  types: ['Product'],
  filters: {
    'price.gte': 50,
    'price.lte': 500,
    category: 'Office Supplies',
  },
  sort: {
    field: 'price',
    order: 'asc',
  },
})

// Find similar products (vector search) → https://actions.org.ai/find.Product
const productEmbedding = await generateEmbedding('High-performance laptop for developers')

const similarProducts = await api.searches.vector(productEmbedding, {
  types: ['Product'],
  filters: {
    category: 'Electronics',
    'price.lte': 2000,
  },
  limit: 10,
})

Semantic Abstraction: find.Product

Search orders by status, date, customer, and more:

// Find recent orders → https://actions.org.ai/find.Order
const recentOrders = await api.searches.query({
  query: 'orders',
  types: ['Order'],
  filters: {
    'orderDate.gte': '2024-10-01',
  },
  sort: {
    field: 'orderDate',
    order: 'desc',
  },
  pagination: {
    page: 1,
    pageSize: 50,
  },
})

// Find orders by customer → https://actions.org.ai/find.Order
const customerOrders = await api.searches.query({
  query: 'customer orders',
  types: ['Order'],
  filters: {
    'customer.$id': 'cust-123',
  },
})

// Find pending orders → https://actions.org.ai/find.Order
const pendingOrders = await api.searches.query({
  query: 'pending',
  types: ['Order'],
  filters: {
    status: 'pending',
    'total.gte': 100,
  },
})

Semantic Abstraction: find.Order

Search articles, documentation, and other content semantically:

// Find articles by topic → https://actions.org.ai/find.Article
const aiArticles = await api.searches.query({
  query: 'artificial intelligence machine learning',
  types: ['Article'],
  filters: {
    status: 'published',
    'publishDate.gte': '2024-01-01',
  },
})

// Semantic article search → https://actions.org.ai/find.Article
const queryEmbedding = await generateEmbedding('How to implement business automation using AI')

const relevantArticles = await api.searches.vector(queryEmbedding, {
  types: ['Article', 'Documentation'],
  filters: {
    status: 'published',
  },
  limit: 10,
})

// Find popular content → https://actions.org.ai/find.Article
const popularContent = await api.searches.query({
  query: 'popular articles',
  types: ['Article'],
  filters: {
    'views.gte': 1000,
  },
  sort: {
    field: 'views',
    order: 'desc',
  },
})

Semantic Abstraction: find.Article

Filter Operators

Comparison Operators

// Greater than
filters: {
  'price.gt': 100  // price > 100
}

// Greater than or equal
filters: {
  'price.gte': 100  // price >= 100
}

// Less than
filters: {
  'price.lt': 1000  // price < 1000
}

// Less than or equal
filters: {
  'price.lte': 1000  // price <= 1000
}

// Equal
filters: {
  status: 'active'  // status === 'active'
}

// Not equal
filters: {
  'status.ne': 'cancelled'  // status !== 'cancelled'
}

Array Operators

// In array
filters: {
  'status.in': ['pending', 'processing', 'completed']
}

// Not in array
filters: {
  'status.nin': ['cancelled', 'failed']
}

// Contains
filters: {
  'tags.contains': 'urgent'
}

String Operators

// Starts with
filters: {
  'email.startsWith': 'admin@'
}

// Ends with
filters: {
  'email.endsWith': '@company.com'
}

// Contains substring
filters: {
  'name.contains': 'corp'
}

// Case-insensitive match
filters: {
  'name.icontains': 'acme'  // Matches 'ACME', 'Acme', 'acme'
}

Date Operators

// Date range
filters: {
  'createdAt.gte': '2024-01-01',
  'createdAt.lte': '2024-12-31'
}

// Relative dates
filters: {
  'createdAt.gte': new Date(Date.now() - 7 * 86400000).toISOString()  // Last 7 days
}

Pagination

Basic Pagination

async function getAllResults(query: BusinessQuery) {
  const allResults = []
  let page = 1
  const pageSize = 100

  while (true) {
    const results = await api.searches.query({
      ...query,
      pagination: { page, pageSize },
    })

    allResults.push(...results)

    if (results.length < pageSize) {
      break // Last page
    }

    page++
  }

  return allResults
}

// Use it
const allCustomers = await getAllResults({
  query: 'customers',
  types: ['Customer'],
})

Cursor-Based Pagination

async function paginateWithCursor(query: BusinessQuery) {
  const allResults = []
  let cursor = null

  while (true) {
    const results = await api.searches.query({
      ...query,
      pagination: {
        cursor,
        pageSize: 100,
      },
    })

    allResults.push(...results)

    if (results.length === 0 || !results.nextCursor) {
      break
    }

    cursor = results.nextCursor
  }

  return allResults
}

Sorting

Single Field Sort

// Sort by single field
const results = await api.searches.query({
  query: 'customers',
  types: ['Customer'],
  sort: {
    field: 'createdAt',
    order: 'desc',
  },
})

Multiple Field Sort

// Sort by multiple fields (client-side)
const results = await api.searches.query({
  query: 'customers',
  types: ['Customer'],
})

results.sort((a, b) => {
  // First by tier
  if (a.tier !== b.tier) {
    return a.tier.localeCompare(b.tier)
  }
  // Then by revenue
  return (b.revenue || 0) - (a.revenue || 0)
})

Advanced Patterns

async function facetedSearch(query: string) {
  // Get all results
  const results = await api.searches.query({
    query,
    types: ['Product'],
  })

  // Calculate facets (client-side)
  const facets = {
    categories: {},
    priceRanges: {
      '0-50': 0,
      '50-100': 0,
      '100-500': 0,
      '500+': 0,
    },
    availability: {},
  }

  results.forEach((product) => {
    // Category facet
    facets.categories[product.category] = (facets.categories[product.category] || 0) + 1

    // Price range facet
    if (product.price < 50) facets.priceRanges['0-50']++
    else if (product.price < 100) facets.priceRanges['50-100']++
    else if (product.price < 500) facets.priceRanges['100-500']++
    else facets.priceRanges['500+']++

    // Availability facet
    facets.availability[product.availability] = (facets.availability[product.availability] || 0) + 1
  })

  return { results, facets }
}

const { results, facets } = await facetedSearch('laptop')
console.log('Facets:', facets)

Search with Highlighting

async function searchWithHighlights(query: string) {
  const results = await api.searches.query({
    query,
    types: ['Article'],
  })

  // Add highlights (client-side)
  return results.map((article) => ({
    ...article,
    highlighted: {
      title: highlightText(article.title, query),
      description: highlightText(article.description, query),
    },
  }))
}

function highlightText(text: string, query: string): string {
  const regex = new RegExp(`(${query})`, 'gi')
  return text.replace(regex, '<mark>$1</mark>')
}
async function autocomplete(prefix: string, type: string) {
  const results = await api.searches.query({
    query: prefix,
    types: [type],
    filters: {
      'name.startsWith': prefix,
    },
    pagination: {
      page: 1,
      pageSize: 10,
    },
  })

  return results.map((r) => ({
    id: r.$id,
    label: r.name,
    value: r.$id,
  }))
}

// Use it
const suggestions = await autocomplete('acm', 'Customer')
// [
//   { id: 'cust-1', label: 'Acme Corp', value: 'cust-1' },
//   { id: 'cust-2', label: 'Acme Industries', value: 'cust-2' }
// ]

Best Practices

1. Use Specific Queries

// ✅ Good - specific query
await api.searches.query({
  query: 'enterprise customers in san francisco',
  types: ['Customer'],
  filters: { tier: 'enterprise', 'address.city': 'San Francisco' },
})

// ❌ Avoid - too broad
await api.searches.query({
  query: 'customers',
})

2. Limit Result Sets

// ✅ Good - pagination and limits
await api.searches.query({
  query: 'products',
  types: ['Product'],
  pagination: { page: 1, pageSize: 50 },
})

// ❌ Avoid - fetching everything
await api.searches.query({
  query: 'products',
  types: ['Product'],
  // No pagination - could return thousands
})

3. Use Appropriate Search Type

// ✅ Good - vector search for semantic similarity
const embedding = await generateEmbedding('enterprise automation solutions')
const similar = await api.searches.vector(embedding, { types: ['Product'] })

// ✅ Good - text search for exact matches
const exact = await api.searches.query({
  query: 'SKU-12345',
  types: ['Product'],
  filters: { sku: 'SKU-12345' },
})

4. Cache Results

const searchCache = new Map()

async function cachedSearch(query: BusinessQuery) {
  const cacheKey = JSON.stringify(query)

  if (searchCache.has(cacheKey)) {
    const { data, timestamp } = searchCache.get(cacheKey)

    // Return cached if fresh (5 minutes)
    if (Date.now() - timestamp < 5 * 60 * 1000) {
      return data
    }
  }

  const results = await api.searches.query(query)
  searchCache.set(cacheKey, { data: results, timestamp: Date.now() })

  return results
}

Next Steps