brX Discovery Connector Schema Mapping - Bloomreach Experience - Headless Digital Experience Platform

brX Discovery Connector Schema Mapping

Introduction

This document explains how the response data from brX Discovery is mapped to the GraphQL Schema models served by the brX GraphQL Service.

For notation purposes, JSONPath expressions are used in this document to show how JSON object and properties are resolved mapped from the response data.

GraphQL Schema Models Overview

As explained in GraphQL Schema of GraphQL Service page, you can browse and explore the brX GraphQL Schema through the Playground UI or the HTML documents directly, but let's have a quick look at the core model schema snippets here.

In product searches through the Product Search API, each product item data is represented by the Item GraphQL Schema model type, each product variant item by ItemVariant, and the whole result set with multiple product items by ItemsPageResult as shown below. 

  "Abstraction for both product item and product item variant"
  interface ItemLike {
    "The ItemId of a product item or product item variant"
    itemId: ItemId!
    "The display name of a product item or product item variant"
    displayName: String
    "The description of a product item or product item variant"
    description: String
    "The ImageSet of a product item or product item variant"
    imageSet: ImageSet
    "The listed price of a product item or product item variant"
    listPrice: Price
    "The purchase price of a product item or product item variant"
    purchasePrice: Price
    // ...SNIP...
  }

  "Product item abstraction"
  type Item implements ItemLike @key(fields: "itemId") {
    "The ItemId of a product item"
    itemId: ItemId!
    "The display name of a product item"
    displayName: String
    "The description of a product item"
    description: String
    "The ImageSet of a product item"
    imageSet: ImageSet
    "The listed price of a product item"
    listPrice: Price
    "The purchase price of a product item"
    purchasePrice: Price
    "Sale price range including the lowest and highest prices to put in the appropriate location"
    salePriceRange: [Float]
    "Price range including the lowest and highest prices to put in the appropriate location"
    priceRange: [Float]
    "All available product item variant dimension names. e.g, [{name:'color'}, {name:'size'}]"
    varAttrTypes: [AttributeType]
    "Product item variants of this product item"
    variants: [ItemVariant]
    // ...SNIP...
  }

  """
  Item identifier that may hold multiple keys.
  e.g, the Commerce Backend Platform specific primary key and other alternate key(s)
  such as SKU, UPC, article number, etc.
  """
  type ItemId {
    "The primary key identifier of a product item maintained by the Commerce Backend Platform"
    id: String!
    "The default alternate key identifier of a product item"
    code: String
  }

  "Product item variant abstraction"
  type ItemVariant implements ItemLike {
    "The ItemId of a product item variant"
    itemId: ItemId!
    "The display name of a product item variant"
    displayName: String
    "The description of a product item variant"
    description: String
    "Flag whether or not this is the master variant"
    master: Boolean
    "The ImageSet of a product item variant"
    imageSet: ImageSet
    "The listed price of a product item variant"
    listPrice: Price
    "The purchase price of a product item variant"
    purchasePrice: Price
    "The main product item which contains this product item variant"
    mainItem: Item
    "Product item variant dimension name-values mappings"
    varAttrs: [Attribute]
    // ...SNIP...
  }

  "Pagination-based product search result"
  type ItemsPageResult implements PageResult {
    "The offset index from which the search result starts"
    offset: Int!
    "The maximum size limit of the search result"
    limit: Int!
    "The item count of the search result"
    count: Int!
    "The total item count of the search result"
    total: Int!
    "The list of product items of the search result"
    items: [Item]!
    "Optional facet result available in this search"
    facetResult: FacetResult
    "Additional query info"
    queryHint: QueryHint
    // ...SNIP...
  }

And product category data is represented by the following type:

  "Product category abstraction"
  type Category {
    "The identifier of this category"
    id: String!
    "The identifier of the parent category of this category"
    parentId: String!
    "The display name of this category"
    displayName: String!
    """
    The optional category path to this category, delimited by '/'.
    Depending on the backend, some category items may appear in multiple tree nodes,
    in which case, this path property can be preferred to the id-parentId pair when constructing category tree nodes.
    """
    path: String
  }

Also, response data from the Autosuggest API is represented by the following:

  "Suggestion search result abstraction, including term suggestions and product item suggestions"
  type SuggestionResult {
    "Term suggestions"
    terms: [String]!
    "Product item suggestions"
    items: [Item]
  }

Product Data Mapping

The response data from the Product search API looks like the following example:

{
  "response":{
    "numFound":86,
    "start":0,
    "docs":[
      {
        "sale_price":115.9,
        "price":115.9,
        "score":0.014999093,
        "description":"",
        "title":"PILOT SPORT A/S 3+",
        "url":"",
        "brand":"Michelin",
        "pid":"PILOT_SPORT_AS3PLUS",
        "thumb_image":"https://demo-images.s3-us-west-2.amazonaws.com/VESTRI_VIRTUAL_V2/92861.png",
        "sale_price_range":[
          115.9,
          115.9
        ],
        "price_range":[
          115.9,
          115.9
        ],
        "variants":[
          {
            "sku_swatch_images":[
              "92861"
            ],
            "sku_thumb_images":[
              "https://demo-images.s3-us-west-2.amazonaws.com/VESTRI_VIRTUAL_V2/92861.png"
            ]
          },
          {
            "sku_swatch_images":[
              "56201"
            ],
            "sku_thumb_images":[
              "https://demo-images.s3-us-west-2.amazonaws.com/VESTRI_VIRTUAL_V2/56201.png"
            ]
          },
          {
            "sku_swatch_images":[
              "80472"
            ],
            "sku_thumb_images":[
              "https://demo-images.s3-us-west-2.amazonaws.com/VESTRI_VIRTUAL_V2/80472.png"
            ]
          }
        ]
      },
    // ...SNIP...
    ]
  },
  "facet_counts":{
    "facet_ranges":{

    },
    "facet_fields":{
      "category":[
        {
          "count":15,
          "crumb":"/VPA_VEHICLE_ADDONS",
          "cat_name":"Vehicle Addons",
          "parent":"",
          "cat_id":"VPA_VEHICLE_ADDONS",
          "tree_path":"/VPA_VEHICLE_ADDONS,Vehicle Addons"
        },
        {
          "count":14,
          "crumb":"/VPA_VEHICLE_ADDONS/VPA_VA_MCLASS",
          "cat_name":"M-Class",
          "parent":"VPA_VEHICLE_ADDONS",
          "cat_id":"VPA_VA_MCLASS",
          "tree_path":"/VPA_VEHICLE_ADDONS,Vehicle Addons/VPA_VA_MCLASS,M-Class"
        },
        {
          "count":10,
          "crumb":"/VPA_VEHICLE_ADDONS/VPA_VA_T50",
          "cat_name":"T50",
          "parent":"VPA_VEHICLE_ADDONS",
          "cat_id":"VPA_VA_T50",
          "tree_path":"/VPA_VEHICLE_ADDONS,Vehicle Addons/VPA_VA_T50,T50"
        },
        {
          "count":28,
          "crumb":"/VESTRI_BM_APPAREL",
          "cat_name":"Apparel",
          "parent":"",
          "cat_id":"VESTRI_BM_APPAREL",
          "tree_path":"/VESTRI_BM_APPAREL,Apparel"
        },
        {
          "count":9,
          "crumb":"/VPA_VEHICLE_ADDONS/VPA_VA_XCLASS",
          "cat_name":"X-Class",
          "parent":"VPA_VEHICLE_ADDONS",
          "cat_id":"VPA_VA_XCLASS",
          "tree_path":"/VPA_VEHICLE_ADDONS,Vehicle Addons/VPA_VA_XCLASS,X-Class"
        },
        // ...SNIP...
      ],
      "brand":[
        {
          "count":80,
          "name":"Vestri"
        },
        // ...SNIP...
      ],
      "colors":[
        {
          "count":18,
          "name":"black"
        },
        {
          "count":19,
          "name":"blue"
        },
        // ...SNIP...
      ],
      // ...SNIP...
    },
    // ...SNIP...
  },
  // ...SNIP...
}

When finding multiple product items data (e.g, GraphQL queries such as findItemsByKeywordfindItemsByCategory, etc.), the main response data object is of type ItemsPageResult, being mapped as follows:

Mapping for ItemsPageResult
Field of ItemsPageResult Resolving JSONPath expression from response Notes
offset

$.response.start

 
limit

 

Set to the limit query input parameter.
count

($.response.docs).length

 
total

$.response.numFound

 
items

 

See the Mapping for Item table below.
facetResult

$.facet_count.facet_fields

Constructs facet navigation information as FacetResult schema type, using the resolved facet fields.
queryHint

{
  "autoCorrectQuery": $.autoCorrectQuery,
  "autoCorrectQuerySet": $.did_you_mean,
  "redirectHint": {
    "url": keywordRedirect['redirected url'],
    "query": keywordRedirect['original query'],
    "newQuery": keywordRedirect['redirected query']
  }
}

See the following pages for detail:

Each product item data in the $.response.docs is mapped to a Item model in ItemsPageResult.items array as follows:

Mapping for Item
Field of Item JSONPath on $.response.docs[*] Notes

itemId

{
  "id": pid,
  "code": variants[0].sku_swatch_images[0]
}
itemId field consists of id and code properties, each of which is extracted from the corresponding JSONPath expression.
If the code property is not resolved, the pid value for the id field is used for the property, too.

displayName

title  

description

description  

imageSet

{
  "original": {
    "link": thumb_image
  },
  "thumbnail": {
    "link": thumb_image
  } 
}

 

listPrice

price  

purchasePrice

sale_price  

salePriceRange

sale_price_range  

priceRange

price_range  

variants

variants See the Mapping for ItemVariant table below for details.

customAttrs

  See the answer for the question, "How can I include extra custom fields from the brSM API response?" in the FAQ page.
Mapping for ItemVariant
Field of ItemVariant JSONPath on $.response.docs[*].variants[*] Notes

itemId

{
  "id": pid,
  "code": variants[0].sku_swatch_images[0]
}
itemId field consists of id and code properties, each of which is extracted from the corresponding JSONPath expression.
If the code property is not resolved, the pid value for the id field is used for the property, too.

displayName

  Same as the parent product Item's displayName property.

description

  Same as the parent product Item's description property.

imageSet

{
  "original": {
    "link": sku_thumb_images[0]
  },
  "thumbnail": {
    "link": sku_thumb_images[0]
  } 
}

 

listPrice

  Same as the parent product Item's listPrice property.

purchasePrice

  Same as the parent product Item's purchasePrice property.

mainItem

  The parent product Item which has all variants.

customAttrs

  See the answer for the question, "How can I include extra custom fields from the brSM API response?" in the FAQ page.

Category Data Mapping

When finding categories (i.e. findCategories GraphQL query), the main response data object is an array of Category models. For a single category finding (i.e. findCategoryByID GraphQL query), it is a single Category model if found.

Internally the queries use the same Product search API and the response looks like the following:

{
  "response":{
    "numFound":86,
    "start":1,
    "docs":[
      // ...SNIP...
    ]
  },
  "facet_counts":{
    "facet_ranges":{

    },
    "facet_fields":{
      "category":[
        {
          "count":15,
          "crumb":"/VPA_VEHICLE_ADDONS",
          "cat_name":"Vehicle Addons",
          "parent":"",
          "cat_id":"VPA_VEHICLE_ADDONS",
          "tree_path":"/VPA_VEHICLE_ADDONS,Vehicle Addons"
        },
        {
          "count":14,
          "crumb":"/VPA_VEHICLE_ADDONS/VPA_VA_MCLASS",
          "cat_name":"M-Class",
          "parent":"VPA_VEHICLE_ADDONS",
          "cat_id":"VPA_VA_MCLASS",
          "tree_path":"/VPA_VEHICLE_ADDONS,Vehicle Addons/VPA_VA_MCLASS,M-Class"
        },
        {
          "count":10,
          "crumb":"/VPA_VEHICLE_ADDONS/VPA_VA_T50",
          "cat_name":"T50",
          "parent":"VPA_VEHICLE_ADDONS",
          "cat_id":"VPA_VA_T50",
          "tree_path":"/VPA_VEHICLE_ADDONS,Vehicle Addons/VPA_VA_T50,T50"
        },
        {
          "count":28,
          "crumb":"/VESTRI_BM_APPAREL",
          "cat_name":"Apparel",
          "parent":"",
          "cat_id":"VESTRI_BM_APPAREL",
          "tree_path":"/VESTRI_BM_APPAREL,Apparel"
        },
        {
          "count":9,
          "crumb":"/VPA_VEHICLE_ADDONS/VPA_VA_XCLASS",
          "cat_name":"X-Class",
          "parent":"VPA_VEHICLE_ADDONS",
          "cat_id":"VPA_VA_XCLASS",
          "tree_path":"/VPA_VEHICLE_ADDONS,Vehicle Addons/VPA_VA_XCLASS,X-Class"
        },
        // ...SNIP...
      ],
      // ...SNIP...
    },
    // ...SNIP...
  },
  // ...SNIP...
}

Each category item data in the $.response.facet_counts.facet_fields.category array is mapped to a Category model like the following:

Mapping for Category
Field of Category JSONPath on $.response.facet_counts.facet_fields.category[*] Notes

id

cat_id  

parentId

parent  

displayName

cat_name  

path

tree_path

 

Autosuggest Data Mapping

The response data from the Autosuggest API looks like the following example:

{
  "queryContext":{
    "originalQuery":"b"
  },
  "suggestionGroups":[
    {
      "catalogName":"example_com",
      "view":"default",
      "querySuggestions":[
        {
          "query":"boots",
          "displayText":"boots"
        },
        {
          "query":"backpack",
          "displayText":"backpack"
        },
        {
          "query":"bench",
          "displayText":"bench"
        },
        // ...SNIP...
      ],
      "searchSuggestions":[
        {
          "sale_price":40,
          "url":"https://www.example.com/not-available/craftsman-safety-boots-size-8/5055160047421_BQ.prd?_br_psugg_q=boots",
          "pid":"5055160047421_BQ",
          "thumb_image":"//king.scene7.com/is/image/King/productTemplate?$baseImage=King/5055160047421_01bq",
          "title":"Craftsman Safety boots, Size 8"
        },
        {
          "sale_price":25,
          "url":"https://www.example.com/not-available/site-granite-grey-trainer-boots-size-10/289361_BQ.prd?_br_psugg_q=boots",
          "pid":"289361_BQ",
          "thumb_image":"//king.scene7.com/is/image/King/productTemplate?$baseImage=King/5055338404995_01bq",
          "title":"Site Granite Grey Trainer boots, Size 10"
        },
        {
          "sale_price":40,
          "url":"https://www.example.com/not-available/site-brown-mudguard-dealer-boots-size-8/3663602605942_BQ.prd?_br_psugg_q=boots",
          "pid":"3663602605942_BQ",
          "thumb_image":"//king.scene7.com/is/image/King/productTemplate?$baseImage=King/3663602605942_01bq",
          "title":"Site Brown Mudguard Dealer boots, Size 8"
        },
        // ...SNIP...
      ],
      // ...SNIP...
    }
  ]
}

When looking up suggestions (i.e. findSuggestions GraphQL query), the main response data object is of type SuggestionResult, being mapped as follows:

Mapping for SuggestionResult
Field of SuggestionResult Resolving JSONPath expression from response Notes

terms

$.suggestionGroups[*].querySuggestions[*].query  

items

$.suggestionGroups[*].searchSuggestions[*] See the Mapping for Item table above for detail on how each product item is mapped.
Did you find this page helpful?
How could this documentation serve you better?
On this page
    Did you find this page helpful?
    How could this documentation serve you better?