Documentation
Feedback
Guides
Learning Center

Learning Center
Learning Center
GraphQL: Retrieving data from Master Data
View in Portuguese
This content was migrated from the VTEX Learning Center and is no longer being actively maintained. For the most accurate and up-to-date information, please check the official documentation.

Introduction

Now that we have updated the product count, we need to retrieve the top n most viewed products. We can, then, use Master Data to retrieve the product page view data and sort by the count field. We can also limit the length of retrieved products, creating a customized size rank of most-visited products.

GraphQL

To get these product page views, we will use GraphQL, the technology used by VTEX IO for data fetching, to implement a query to Master Data. GraphQL allows us to implement queries in a simple and easy way, specifying the data you want to retrieve. This makes your API reliable since GraphQL controls the data fetched instead of the server itself.

It's also the only possible way to create an interface between services and front end applications.

Therefore, GraphQL uses types and a query schema to specify the data retrieved and resolvers to get the exact data needed.

Retrieving data from Master Data

  1. Inside the /graphql directory, create a folder called /types. In this folder, create the productView.graphql file and declare the type of the product list we want to retrieve:


    _10
    # /graphql/types/productView.graphql
    _10
    type ProductView {
    _10
    slug: String
    _10
    count: Int
    _10
    }

  2. Still in the /graphql directory, define the schema in the schema.graphql file:


    _10
    type Query {
    _10
    productList(topN: Int): [ProductView]
    _10
    }

    Keep in mind that the schema will define the structure of our query and the retrieved data.

    Also, in this declaration you can include directives. In some cases, it is required, for example, if you need to get the user token or use cookies (e.g.: OrderForm). To read more about it, check out this link.

  3. With the schema, types, and the query defined, we need to create the query's resolver. The resolver is what happens when a query is executed. In our case, we want to perform a scroll on Master Data, ordering by the count (as we want to get a topmost viewed products) and limiting the page size (the top n). To define this resolver, in the /node/resolvers directory, create the file products.ts and do the following:


    _17
    // node/resolvers/products.ts
    _17
    import { COURSE_ENTITY } from '../utils/constants'
    _17
    _17
    export const productList = async (
    _17
    _: any,
    _17
    { topN }: { topN: number },
    _17
    { clients: { masterdata } }: Context
    _17
    ) =>
    _17
    masterdata
    _17
    .scrollDocuments({
    _17
    dataEntity: COURSE_ENTITY,
    _17
    fields: ['count', 'slug'],
    _17
    schema: 'v1',
    _17
    size: topN,
    _17
    sort: `count DESC`,
    _17
    })
    _17
    .then(({ data }) => data)

    Note: you can check the Master Data scroll documentation in this link.

  4. Import the resolver on the index.ts file:


_10
import { productList } from './resolvers/products'

  1. At last, we need to update the index.ts file to set up the resolver and the query. Complete the service declaration as below:


    _10
    },
    _10
    graphql: {
    _10
    resolvers: {
    _10
    Query: {
    _10
    productList,
    _10
    },
    _10
    },
    _10
    },
    _10
    })

    And, also, remember to add the graphql builder on the manifest.json:


    _10
    //manifest.json
    _10
    "builders": {
    _10
    + "graphql": "1.x",
    _10
    "docs": "0.x",
    _10
    "node": "6.x"
    _10
    },

    Finally, link the app and you should get a GraphQL route. The result should be like this:

    {"base64":"  ","img":{"width":1840,"height":744,"type":"png","mime":"image/png","wUnits":"px","hUnits":"px","length":619127,"url":"https://user-images.githubusercontent.com/43679629/82947940-3c4faa80-9f77-11ea-8bfa-138d11cdec1f.png"}}


Answer sheet

See answer sheet for index.ts
index.ts

_64
// node/index.ts
_64
import {
_64
LRUCache,
_64
Service,
_64
ServiceContext,
_64
ParamsContext,
_64
RecorderState,
_64
method,
_64
} from '@vtex/api'
_64
import { Clients } from './clients'
_64
import { productList } from './resolvers/products'
_64
import { updateLiveUsers } from './event/liveUsersUpdate'
_64
import { analytics } from './handlers/analytics'
_64
_64
const TREE_SECONDS_MS = 3 * 1000
_64
const CONCURRENCY = 10
_64
_64
// Create a LRU memory cache for the Status client.
_64
// The @vtex/api HttpClient respects Cache-Control headers and uses the provided cache.
_64
const memoryCache = new LRUCache<string, any>({ max: 5000 })
_64
metrics.trackCache('status', memoryCache)
_64
_64
declare global {
_64
type Context = ServiceContext<Clients, State>
_64
_64
interface State extends RecorderState {
_64
code: number
_64
}
_64
}
_64
_64
export default new Service<Clients, State, ParamsContext>({
_64
clients: {
_64
implementation: Clients,
_64
options: {
_64
default: {
_64
retries: 2,
_64
timeout: 10000,
_64
},
_64
events: {
_64
exponentialTimeoutCoefficient: 2,
_64
exponentialBackoffCoefficient: 2,
_64
initialBackoffDelay: 50,
_64
retries: 1,
_64
timeout: TREE_SECONDS_MS,
_64
concurrency: CONCURRENCY,
_64
},
_64
},
_64
},
_64
events: {
_64
liveUsersUpdate: updateLiveUsers,
_64
},
_64
graphql: {
_64
resolvers: {
_64
Query: {
_64
productList,
_64
},
_64
},
_64
},
_64
routes: {
_64
analytics: method({
_64
GET: [analytics],
_64
}),
_64
},
_64
})

See answer sheet for manifest.json
manifest.json

_32
{
_32
"name": "backend-course",
_32
"vendor": "vtex",
_32
"version": "0.0.2",
_32
"title": "Backend Course",
_32
"description": "Reference app for the Backend Course",
_32
"builders": {
_32
"graphql": "1.x",
_32
"docs": "0.x",
_32
"node": "6.x"
_32
},
_32
"scripts": {
_32
"prereleasy": "bash lint.sh"
_32
},
_32
"credentialType": "absolute",
_32
"policies": [
_32
{
_32
"name": "ADMIN_DS"
_32
},
_32
{
_32
"name": "outbound-access",
_32
"attrs": {
_32
"host": "api.vtex.com",
_32
"path": "/dataentities/*"
_32
}
_32
}
_32
],
_32
"dependencies": {
_32
"vtex.events-example": "0.x"
_32
},
_32
"$schema": "https://raw.githubusercontent.com/vtex/node-vtex-api/master/gen/manifest.schema"
_32
}

See answer sheet for product.ts
product.ts

_17
// node/resolvers/product.ts
_17
import { COURSE_ENTITY } from '../utils/constants'
_17
_17
export const productList = async (
_17
_: any,
_17
{ topN }: { topN: number },
_17
{ clients: { masterdata } }: Context
_17
) =>
_17
masterdata
_17
.scrollDocuments({
_17
dataEntity: COURSE_ENTITY,
_17
fields: ['count', 'slug'],
_17
schema: 'v1',
_17
size: topN,
_17
sort: `count DESC`,
_17
})
_17
.then(({ data }) => data)

See answer sheet for productList.graphql
productList.graphql

_10
# graphql/types/productList.graphql
_10
type ProductList {
_10
slug: String
_10
count: Int
_10
}

See answer sheet for schema.graphql
schema.graphql

_10
# graphql/schema.graphql
_10
type Query {
_10
productList(topN: Int): [ProductView]
_10
}

On this page