All Release Notes
Added Product Projection Search to GraphQL API
18 August 2021
Composable Commerce
HTTP API
Enhancement
GraphQLSearchProduct catalog
ProductProjection Search can now be performed using the GraphQL API.

Changes:

  • [GraphQL API] Added the following types to the GraphQL schema: CategoryOrderHintProductSearch, DimensionsProductSearch, DiscountedProductSearchPriceValue, ExistsFilterInput, FacetResult, FacetResultValue, ImageProductSearch, MissingFacetInput, MissingFilterInput, PriceSelectorInput, ProductPriceSearch, ProductProjection, ProductProjectionSearchResult, ProductSearchPriceTier, ProductSearchVariant, ProductSearchVariantAvailabilitiesResult, ProductSearchVariantAvailability, ProductSearchVariantAvailabilityWithChannel, ProductSearchVariantAvailabilityWithChannels, RangeCount, RangeCountDouble, RangeCountLong, RangeElementInput, RangeFacetInput, RangeFacetResult, RangeFilterInput, RawProductSearchAttribute, SearchFacetInput, SearchFacetModelInput, SearchFilterInput, SearchFilterModelInput, SearchKeywordProductSearch, SearchKeywordsProductSearch, SuggestTokenizerProductSearch,CustomSuggestTokenizerProductSearch,WhitespaceSuggestTokenizerProductSearch, TermCount, TermsFacetInput, TermsFacetResult, TreeFacetInput, TreeFilterInput, ValueCountFacetInput, ValueFacetInput, ValueFacetResult, ValueFilterInput.
  • [GraphQL API] Changed the Query type:
    • Added the productProjectionSearch field to the Query type.

The following changes were introduced in terms of GraphQL SDL:

extend type Query {
  productProjectionSearch(locale: Locale, text: String, facets: [SearchFacetInput!]! = [], filters: [SearchFilterInput!]! = [], queryFilters: [SearchFilterInput!]! = [], facetFilters: [SearchFilterInput!]! = [], sorts: [String!]! = [], limit: Int! = 10, offset: Int! = 0, fuzzy: Boolean! = false, fuzzyLevel: Int, priceSelector: PriceSelectorInput, markMatchingVariant: Boolean! = false,

    "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
    storeProjection: String,

    "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
    localeProjection: [Locale!], staged: Boolean = false): ProductProjectionSearchResult!
}

type CategoryOrderHintProductSearch {
  categoryId: String!
  orderHint: String!
}

type DimensionsProductSearch {
  width: Int!
  height: Int!
}

type DiscountedProductSearchPriceValue {
  value: BaseMoney!
  discountRef: Reference!
  discount: ProductDiscount
}

input ExistsFilterInput {
  path: String!
}

interface FacetResult {
  type: String!
}

type FacetResultValue {
  facet: String!
  value: FacetResult!
}

type ImageProductSearch {
  url: String!
  dimensions: DimensionsProductSearch!
  label: String
}

input MissingFacetInput {
  path: String!
  alias: String
}

input MissingFilterInput {
  path: String!
}

input PriceSelectorInput {
  currency: Currency!
  country: Country
  customerGroup: ReferenceInput
  channel: ReferenceInput
  date: Instant!
}

scalar Instant

type ProductPriceSearch {
  id: String
  value: BaseMoney!
  country: Country
  customerGroup: CustomerGroup
  customerGroupRef: Reference
  channel: Channel
  channelRef: Reference
  validFrom: DateTime
  validUntil: DateTime
  discounted: DiscountedProductSearchPriceValue
  tiers: [ProductSearchPriceTier!]
  custom: CustomFieldsType
}

type ProductProjection {
  id: String!
  version: Long!
  createdAt: DateTime!
  lastModifiedAt: DateTime!
  productTypeRef: Reference!
  productType: ProductTypeDefinition
  name(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  nameAllLocales: [LocalizedString!]!
  description(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  descriptionAllLocales: [LocalizedString!]
  slug(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  slugAllLocales: [LocalizedString!]!
  categoryOrderHints: [CategoryOrderHintProductSearch!]!
  categoriesRef: [Reference!]!
  categories: [Category!]!
  searchKeywords: [SearchKeywordsProductSearch!]!
  metaTitle(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  metaTitleAllLocales: [LocalizedString!]
  metaKeywords(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  metaKeywordsAllLocales: [LocalizedString!]
  metaDescription(
    "String is defined for different locales. This argument specifies the desired locale."
    locale: Locale,

    "List of languages the client is able to understand, and which locale variant is preferred."
    acceptLanguage: [Locale!]): String
  metaDescriptionAllLocales: [LocalizedString!]
  hasStagedChanges: Boolean!
  published: Boolean!
  masterVariant: ProductSearchVariant!
  variants: [ProductSearchVariant!]!
  taxCategoryRef: Reference
  taxCategory: TaxCategory
  stateRef: Reference
  state: State
  reviewRatingStatistics: ReviewRatingStatistics
}

type ProductProjectionSearchResult {
  offset: Int!
  count: Int!
  total: Int!
  results: [ProductProjection!]!
  facets: [FacetResultValue!]!
}

type ProductSearchPriceTier {
  minimumQuantity: Int!
  value: BaseMoney!
}

type ProductSearchVariant {
  id: Int!
  key: String
  sku: String
  prices: [ProductPriceSearch!]

  "Returns a single price based on the price selection rules."
  price(currency: Currency!, country: Country, customerGroupId: String, channelId: String, date: DateTime): ProductPriceSearch
  images: [ImageProductSearch!]!
  assets: [Asset!]!
  availability: ProductSearchVariantAvailabilityWithChannels

  "This field contains raw attributes data"
  attributesRaw(
    """
    The names of the attributes to include.

    If neither `includeNames` nor `excludeNames` are provided, then all attributes are returned.
    """
    includeNames: [String!],

    """
    The names of the attributes to exclude.

    If neither `includeNames` nor `excludeNames` are provided, then all attributes are returned.
    """
    excludeNames: [String!]): [RawProductSearchAttribute!]!
}

"Product variant availabilities"
type ProductSearchVariantAvailabilitiesResult {
  limit: Int
  offset: Int
  total: Int!
  results: [ProductSearchVariantAvailabilityWithChannel!]!
}

"Product variant availability"
type ProductSearchVariantAvailability {
  isOnStock: Boolean!
  restockableInDays: Int
  availableQuantity: Long
}

type ProductSearchVariantAvailabilityWithChannel {
  channelRef: Reference!
  channel: Channel
  availability: ProductSearchVariantAvailability!
}

type ProductSearchVariantAvailabilityWithChannels {
  noChannel: ProductSearchVariantAvailability
  channels(
    """
    The IDs of channels to include.

    If neither `includeChannelIds` nor `excludeChannelIds` are provided, then all channels are returned.
    """
    includeChannelIds: [String!],

    """
    The IDs of channels to exclude.

    If neither `includeChannelIds` nor `excludeChannelIds` are provided, then all channels are returned.
    """
    excludeChannelIds: [String!], limit: Int, offset: Int): ProductSearchVariantAvailabilitiesResult!
}

interface RangeCount {
  type: String!
}

type RangeCountDouble implements RangeCount {
  from: Float!
  fromStr: String!
  to: Float!
  toStr: String!
  count: Int!
  productCount: Int
  totalCount: Int!
  total: Float!
  min: Float!
  max: Float!
  mean: Float!
  type: String!
}

type RangeCountLong implements RangeCount {
  from: Long!
  fromStr: String!
  to: Long!
  toStr: String!
  count: Int!
  productCount: Int
  totalCount: Int!
  total: Long!
  min: Long!
  max: Long!
  mean: Float!
  type: String!
}

input RangeElementInput {
  from: String!
  to: String!
}

input RangeFacetInput {
  path: String!
  ranges: [RangeElementInput!]!
  alias: String
  countProducts: Boolean! = false
}

type RangeFacetResult implements FacetResult {
  dataType: String!
  ranges: [RangeCount!]!
  type: String!
}

input RangeFilterInput {
  path: String!
  ranges: [RangeElementInput!]!
}

type RawProductSearchAttribute {
  name: String!
  value: Json!
}

input SearchFacetInput {
  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  model: SearchFacetModelInput
  string: String
}

input SearchFacetModelInput {
  terms: TermsFacetInput
  value: ValueFacetInput
  range: RangeFacetInput
  tree: TreeFacetInput
  valueCount: ValueCountFacetInput
  missing: MissingFacetInput
}

input SearchFilterInput {
  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  model: SearchFilterModelInput
  string: String
}

input SearchFilterModelInput {
  value: ValueFilterInput
  range: RangeFilterInput
  missing: MissingFilterInput
  exists: ExistsFilterInput
  tree: TreeFilterInput
}

type SearchKeywordProductSearch {
  text: String!
  suggestTokenizer: SuggestTokenizerProductSearch
}

type SearchKeywordsProductSearch {
  locale: Locale!
  searchKeywords: [SearchKeywordProductSearch!]!
}

interface SuggestTokenizerProductSearch {
  type: String!
}

type CustomSuggestTokenizerProductSearch implements SuggestTokenizerProductSearch {
  inputs: [String!]!
  type: String!
}

type WhitespaceSuggestTokenizerProductSearch implements SuggestTokenizerProductSearch {
  type: String!
}

type TermCount {
  term: String!
  count: Int!
  productCount: Int
}

input TermsFacetInput {
  path: String!
  alias: String
  countProducts: Boolean! = false
}

type TermsFacetResult implements FacetResult {
  dataType: String!
  missing: Int!
  total: Int!
  other: Int!
  terms: [TermCount!]!
  type: String!
}

input TreeFacetInput {
  path: String!
  rootValues: [String!]!
  subTreeValues: [String!]!
  alias: String
  countProducts: Boolean! = false
}

input TreeFilterInput {
  path: String!
  rootValues: [String!]!
  subTreeValues: [String!]!
}

input ValueCountFacetInput {
  path: String!
  alias: String
}

input ValueFacetInput {
  path: String!
  values: [String!]!
  alias: String
  countProducts: Boolean! = false
}

type ValueFacetResult implements FacetResult {
  count: Int!
  productCount: Int
  type: String!
}

input ValueFilterInput {
  path: String!
  values: [String!]!
}