.md

Query results

Retrieve filtered data with items(). Control result ordering with sort, limit data with pagination (start/count), and reduce payload size with projection.

Syntax

list.catalog.query.items({
  sort?: { attributes: string[], order: ('ASC' | 'DESC')[] },
  start?: number,
  count?: number,
  projection?: { [field: string]: boolean }
})

Parameters

sort.attributesstring[]Optional
Fields to sort by (in priority order)
sort.order('ASC' | 'DESC')[]Optional
Sort direction for each attribute (uppercase; other values are ignored with a warning and the result stays unsorted)
startnumberOptional
Zero-based offset for pagination
countnumberOptional
Maximum items to return
projectionobjectOptional
{ field: true } to return only these fields, { $: true, field: false } to exclude fields. A nested object resolves a reference: { $: true, customer: { name: true } }

Return type

Returns an array of items matching the query with applied options.

// list.catalog.query
items<T>(options?: DcuplListQueryOptions<T>): T[]; // matching items with the requested fields

Usage notes

  • 'ASC' sorts ascending (A-Z, 0-9, oldest first), 'DESC' descending; items without a value sort last in both directions
  • Projection (key is always included): { field: true } only this field, { $: true } all fields, { $: true, field: false } all but this one, { $: true, ref: { $: true } } all fields with this reference resolved
  • Without count, returns ALL matching items
  • Total number of matches (ignoring start/count): list.catalog.fn.metadata().currentSize
  • Always sort before paginating for consistent results
  • Sort attributes and order arrays must have matching lengths; order values are 'ASC' or 'DESC'
  • String sorting is case-insensitive
  • Projection with true includes only specified fields (plus key)
  • Use { $: true, field: false } to exclude specific fields
  • Sort attributes are properties of the item: a dotted attribute such as 'customer.name' is ignored without an error. To sort by a referenced value, add a derived property
  • sort.script runs a custom sort script instead (see Scripts)
  • Conditions passed in items({ queries }) are applied on top of the list query (AND), they do not replace it. Such a call ignores the start, count, sort and projection applied with applyOptions(): pass them in the same items() call
  • Other ways to read results: first(), any(), count(), one({ itemKey }) and many({ itemKeys }) (Catalog API). one() and many() only return items that pass the list query
  • Page formula: start = (pageNumber - 1) * pageSize
  • query.count() counts what items() returns, so a count applied with applyOptions() caps it; use fn.metadata().currentSize for the total

Related methods

  • catalog.fn.facets() — Get value counts for filter UIs
  • catalog.fn.aggregate() — Get totals without fetching items

Related guides/docs

Examples

Basic result retrieval

Get all items matching current query filters.

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

productList.catalog.query.addCondition({
  attribute: 'status',
  operator: 'eq',
  value: 'active',
});

// Get all matching items
const results = productList.catalog.query.items();
console.log('Total items:', results.length);
Pagination with count and start

Retrieve a specific page of results.

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

// Page 1: items 0-19
const page1 = productList.catalog.query.items({
  start: 0,
  count: 20,
});

// Page 2: items 20-39
const page2 = productList.catalog.query.items({
  start: 20,
  count: 20,
});

// Page calculation helper
function getPage(pageNumber: number, pageSize: number) {
  return productList.catalog.query.items({
    start: (pageNumber - 1) * pageSize,
    count: pageSize,
  });
}
Single property sort

Sort results by one field.

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

// Sort by price ascending (lowest first)
const cheapest = productList.catalog.query.items({
  sort: {
    attributes: ['price'],
    order: ['ASC'],
  },
});

// Sort by price descending (highest first)
const expensive = productList.catalog.query.items({
  sort: {
    attributes: ['price'],
    order: ['DESC'],
  },
});
Multi-field sort

Sort by multiple fields with different directions.

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

// Sort by category (A-Z), then price (high to low) within category
const results = productList.catalog.query.items({
  sort: {
    attributes: ['category', 'price'],
    order: ['ASC', 'DESC'],
  },
});

// Featured first, then by rating, then alphabetically
const featured = productList.catalog.query.items({
  sort: {
    attributes: ['featured', 'rating', 'name'],
    order: ['DESC', 'DESC', 'ASC'],
  },
});
Sort with pagination

Always sort before paginating for consistent results.

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

// IMPORTANT: Sort must be consistent across pages
const pageSize = 20;
const currentPage = 1;

const results = productList.catalog.query.items({
  sort: {
    attributes: ['createdAt'],
    order: ['DESC'],
  },
  start: (currentPage - 1) * pageSize,
  count: pageSize,
});

// Get total for pagination UI (all matching items, not just this page)
const totalItems = productList.catalog.fn.metadata().currentSize;
const totalPages = Math.ceil(totalItems / pageSize);
Field projection

Select only specific fields to return.

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

// Only return key, name, price, and thumbnail (reduces payload)
const results = productList.catalog.query.items({
  projection: {
    name: true,
    price: true,
    thumbnail: true,
    // All other fields excluded; key is always included
  },
});

// Exclude specific fields
const withoutDescription = productList.catalog.query.items({
  projection: {
    $: true,             // Include all fields...
    description: false,  // ...except this large text field
  },
});
Complete e-commerce listing

Full example with filters, sort, pagination, and projection.

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

function getProductListing(options: {
  category?: string;
  minPrice?: number;
  maxPrice?: number;
  sortBy: 'price' | 'rating' | 'name';
  sortDir: 'ASC' | 'DESC';
  page: number;
  pageSize: number;
}) {
  const query = productList.catalog.query;
  query.clear();

  // Apply filters
  if (options.category) {
    query.addCondition({
      attribute: 'category',
      operator: 'eq',
      value: options.category,
    });
  }

  // Price range: an 'and' group (two addCondition calls on 'price' would be ORed)
  query.addGroup({
    groupKey: 'price',
    groupType: 'and',
    queries: [
      { attribute: 'price', operator: 'gte', value: options.minPrice ?? 0 },
      { attribute: 'price', operator: 'lte', value: options.maxPrice ?? Number.MAX_SAFE_INTEGER },
    ],
  });

  // Active products only
  query.addCondition({
    attribute: 'status',
    operator: 'eq',
    value: 'active',
  });

  // Sort, paginate, and project
  query.applyOptions({
    sort: {
      attributes: [options.sortBy],
      order: [options.sortDir],
    },
    start: (options.page - 1) * options.pageSize,
    count: options.pageSize,
    projection: {
      name: true,
      price: true,
      thumbnail: true,
      rating: true,
      category: true,
    },
  });
  const results = query.items();

  // Total count for pagination
  const totalItems = productList.catalog.fn.metadata().currentSize;

  return {
    items: results,
    page: options.page,
    pageSize: options.pageSize,
    totalItems,
    totalPages: Math.ceil(totalItems / options.pageSize),
  };
}
Sort by a referenced property

Sort attributes are read from the item itself, so pull the referenced value in with a derived property first.

// A dotted path like 'customer.name' is not a valid sort attribute.
// Derive the customer's name onto the order instead:
dcupl.models.set({
  key: 'Order',
  properties: [
    { key: 'total', type: 'int' },
    {
      key: 'customerName',
      type: 'string',
      derive: { localReference: 'customer', remoteProperty: 'name' },
    },
  ],
  references: [{ key: 'customer', type: 'singleValued', model: 'Customer' }],
});

// ...after dcupl.init():
const orderList = dcupl.lists.create({ modelKey: 'Order' });

// Sort orders by customer name, then by total
const results = orderList.catalog.query.items({
  sort: {
    attributes: ['customerName', 'total'],
    order: ['ASC', 'DESC'],
  },
});
// Get sorted, paginated results
const list = dcupl.lists.create({ modelKey: 'Article' });

// Apply filter
list.catalog.query.addCondition({
  attribute: 'category',
  operator: 'eq',
  value: 'Running',
});

// Get page 1 with sort
const results = list.catalog.query.items({
  sort: {
    attributes: ['price'],
    order: ['ASC']
  },
  start: 0,
  count: 10
});

// Get total count for pagination
const total = list.catalog.fn.metadata().currentSize;
console.log('Showing', results.length, 'of', total);