.md

Text search

Search text fields with the find operator. Wrap the search term in slashes, like /shoe/, to match it anywhere in the value (the text between the slashes is a regular expression), and set regexFlags to i for case-insensitive search. Without slashes, find compares the whole value exactly. Essential for search bars, autocomplete, and text filtering.

Syntax

list.catalog.query.addCondition({
  attribute: string,
  operator: 'find',
  value: string | object, // '/term/' = contains, 'term' = exact, { brand: 'Apple' } = partial object match
  options?: SearchOptions
})

Parameters

attributestringRequired
The text field to search in
operator'find'Required
The find operator for text and pattern matching
valuestring | objectRequired
/term/ matches the term anywhere in the value (regex); a bare term without slashes must equal the whole value. An object matches part of a json value ({ brand: 'Apple' }), see the Query Operators Reference
options.regexFlagsstringOptional
Regex flags for a '/term/' value, e.g. 'i' for case-insensitive. Put flags here, not after the closing slash ('/term/i' is an exact match)
options.transform('lowercase' | 'trim' | 'removeWhitespace')[]Optional
Transform both data and search value before comparison
options.invertbooleanOptional
Exclude matches (find items NOT containing the term). Items without a value are left out too
options.arrayValueHandling'some' | 'every'Optional
For array fields: 'some' (any element) or 'every' (all elements)

Return type

addCondition() returns the updated query (DcuplGlobalQueryOptions); call items() for the matching items:

// list.catalog.query
addCondition(condition: DcuplQuery | DcuplQuery[]): DcuplGlobalQueryOptions<any>; // the list's query
items(options?: DcuplListQueryOptions<T>): T[];

Usage notes

  • '/phone/' matches "Smartphone" and "headphones", not "Phone Case"; with regexFlags: 'i' it matches all three. '/^run/' with 'i' matches "Running Shoes" and "runner", not "outrun". 'Phone Case' (no slashes) matches only that whole value
  • A /regex/ is tested against non-string values as strings: /^1/ on a number attribute matches 150 and 100
  • Transforms: 'lowercase', 'trim' (leading/trailing whitespace) and 'removeWhitespace' (all whitespace)
  • Wrap the term in slashes (/term/) for substring search; a bare string must match the whole value
  • Set regexFlags to i for case-insensitive, user-facing search
  • Escape regex characters (. * + ? ^ $ { } ( ) | [ ] \) in user input before wrapping it in slashes
  • Transforms apply to BOTH the data value AND your search term
  • Use multiple find conditions on same field for OR logic
  • Combine with other operators (eq, gte) for filtered search
  • For suggestions/autocomplete, see catalog.fn.suggest()

Related methods

  • catalog.fn.suggest() — Get value suggestions for autocomplete (case-insensitive prefix match, or a /regex/)

Related guides/docs

Examples

Search with user input

Escape regex characters in user input before wrapping it in slashes.

const productList = dcupl.lists.create({ modelKey: 'Product' });

const escapeRegExp = (text: string) => text.replace(/[.*+?^${}()|[\]\\]/g, (char) => '\\' + char);
const userInput = '  shoe ';

productList.catalog.query.addCondition({
  attribute: 'name',
  operator: 'find',
  value: `/${escapeRegExp(userInput.trim())}/`,
  options: { regexFlags: 'i' },
});

// Matches: "Running Shoes", "Trail Running Shoes", "Snowshoes"
const results = productList.catalog.query.items();
Exact match (no slashes)

A bare string compares the whole value. Transforms normalize both sides before comparing.

const productList = dcupl.lists.create({ modelKey: 'Product' });

// trim: remove leading/trailing whitespace
// removeWhitespace: remove ALL whitespace
productList.catalog.query.addCondition({
  attribute: 'sku',
  operator: 'find',
  value: 'ABC123',
  options: { transform: ['trim', 'removeWhitespace'] },
});

// Matches: " ABC 123 ", "ABC123", "A B C 1 2 3"
// No match: "ABC1234" (a bare string never matches part of a value)
const results = productList.catalog.query.items();
Search multiple fields

Search name OR description by putting both conditions in one or-group.

const productList = dcupl.lists.create({ modelKey: 'Product' });

// Conditions on different attributes are combined with AND,
// so group them with groupType 'or'
productList.catalog.query.addGroup({
  groupKey: 'search',
  groupType: 'or',
  queries: [
    { attribute: 'name', operator: 'find', value: '/waterproof/', options: { regexFlags: 'i' } },
    { attribute: 'description', operator: 'find', value: '/waterproof/', options: { regexFlags: 'i' } },
  ],
});

// Matches: "Waterproof Jacket", and "Hiking Boots" (described as waterproof)
const results = productList.catalog.query.items();
Exclude search terms

Find products NOT containing "refurbished" using invert.

const productList = dcupl.lists.create({ modelKey: 'Product' });

productList.catalog.query.addCondition({
  attribute: 'name',
  operator: 'find',
  value: '/refurbished/',
  options: {
    regexFlags: 'i',
    invert: true, // Exclude matches
  },
});

// Returns products without "refurbished" in the name
const newProducts = productList.catalog.query.items();
Search in array fields

Find products where ANY tag contains the search term.

const productList = dcupl.lists.create({ modelKey: 'Product' });

productList.catalog.query.addCondition({
  attribute: 'tags',
  operator: 'find',
  value: '/sale/',
  options: {
    regexFlags: 'i',
    arrayValueHandling: 'some', // Match if ANY element contains "sale"
  },
});

// Matches: tags = ["summer-sale", "clearance"]
// Matches: tags = ["new", "SALE-2024"]
const saleProducts = productList.catalog.query.items();
Search with category filter

Combine text search with other filters.

const productList = dcupl.lists.create({ modelKey: 'Product' });

// Text search
productList.catalog.query.addCondition({
  attribute: 'name',
  operator: 'find',
  value: '/pro/',
  options: { regexFlags: 'i' },
});

// Combined with category filter (AND logic)
productList.catalog.query.addCondition({
  attribute: 'category',
  operator: 'eq',
  value: 'Electronics',
});

// Result: Electronics products with "pro" in the name
const results = productList.catalog.query.items();
// Case-insensitive substring search
const list = dcupl.lists.create({ modelKey: 'Article' });

// Find products whose name contains "shoe" (any case)
list.catalog.query.addCondition({
  attribute: 'productName',
  operator: 'find',
  value: '/shoe/',
  options: { regexFlags: 'i' },
});

// Get search results
const results = list.catalog.query.items();
console.log('Found:', results.length, 'matching products');