How to get random records from Strapi v4 ? (I answered this question)

Viewed 37

Strapi doesn't have any endpoint to get random data for this purpose you should write some custom code for your endpoint

  1. custom route for that endpoint you want

enter image description here

// path: ./src/api/[your-endpiont]/routes/[custom-route].js

module.exports = {
  "routes": [
    {
      "method": "GET",
      "path": "/[your-endpiont]/random", // you can define everything you want for url endpoint
      "handler": "[your-endpiont].random", // random is defined as a method
      "config": {
        "policies": []
      }
    }
  ]
}

now you have to run yarn develop or npm ... to display a random method in your strapi panel enter image description here Save this setting and retry to reach the random endpoint.

  1. create a function as a service for getting random data in your endpoint API services.
// path: ./src/api/[your-endpiont]/services/[your-endpiont].js

'use strict';

/**
 * news-list service.
 */

const { createCoreService } = require('@strapi/strapi').factories;

module.exports = createCoreService('api::news-list.news-list', ({ strapi }) => ({
    async serviceGetRandom({ locale, id_nin }) { // these parametrs come from query

        function getRandomElementsFromArray(array, numberOfRandomElementsToExtract = 1) {

            const elements = [];

            function getRandomElement(arr) {
                if (elements.length < numberOfRandomElementsToExtract) {
                    const index = Math.floor(Math.random() * arr.length)
                    const element = arr.splice(index, 1)[0];

                    elements.push(element)

                    return getRandomElement(arr)
                } else {
                    return elements
                }
            }

            return getRandomElement([...array])
        }

        const newsListArray = await strapi
            .db
            .query("api::news-list.news-list")
            .findMany({
                where: {
                    locale: locale, // if you have multi-language data
                    $not: {
                        id: id_nin, // depend on where this endpoint API use
                    },
                    publishedAt: {
                        $notNull: true,
                    },
                },
                sort: [{ datetime: 'asc' }],
                limit: 10,
                populate: {
                    content: {
                        populate: {
                            thumbnail: true,
                        },
                    },
                },
                //? filter object throws an error when you used populate object, everything you want to filter properly best write into where{}
                // filters: {
                //     publishedAt: {
                //         $notNull: true,
                //     },
                //     locale: locale
                // }

            })

        if (!newsListArray.length) {
            return null
        }

        return getRandomElementsFromArray(newsListArray, 2)
         
    }
}));

explain code:

Strapi provides a Query Engine API to interact with the database layer at a lower level

strapi.db.query("api::news-list.news-list").findMany({})

The Query Engine allows operations on database entries, I wrote this for my purpose probably you should change based on what you needed

{
                where: {
                    locale: locale,
                    $not: {
                        id: id_nin
                    },
                    publishedAt: {
                        $notNull: true,
                    },
                },
                sort: [{ datetime: 'asc' }],
                limit: 10,
                populate: {
                    content: {
                        populate: {
                            thumbnail: true,
                        },
                    },
                }

}

when you get data from your query, passed it to that function getRandomElementsFromArray(newsListArray, 2) to get some random item (how many random items do you want ? pass the second parameter) At least if your array is null return null otherwise return data

  1. create the controller

Controllers are JavaScript files that contain a set of methods, called actions, reached by the client according to the requested route so we going to call our services in this section

// path: ./src/api/[your-endpoint]/controllers/[your-endpoint].js
'use strict';

/**
 *  news-list controller
 */

const { createCoreController } = require('@strapi/strapi').factories;

module.exports = createCoreController('api::news-list.news-list', ({ strapi }) => ({
    async random(ctx) { // name of this methods related to something we define in route  ("handler": "[your-endpiont].random",)
        
        const entity = await strapi.service('api::news-list.news-list').serviceGetRandom(ctx.query) // call our services, you can send all query you get from url endpoint (notice that you should write your endpoint api in strapi.service("your-endpoint"))
        const sanitizedEntity = await this.sanitizeOutput(entity, ctx);

        return this.transformResponse(sanitizedEntity);
        // console.log(entity);
    }
}));

I call this endpoint in my project nextjs & stapi cms

export const getRandomNewsItem = (id, locale) => {
  return API
    .get(`/news-list/random?locale=${locale}&id_nin=${id}`)
    .then(res => res.data);
};

That's it, I'll hope you all get what to do

all resources you need

https://docs.strapi.io/developer-docs/latest/development/backend-customization/routes.html#creating-custom-routers

https://docs.strapi.io/developer-docs/latest/development/backend-customization/services.html#implementation

https://docs.strapi.io/developer-docs/latest/development/backend-customization/controllers.html#adding-a-new-controller

https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/query-engine-api.html

https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/query-engine/filtering.html#and

https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/entity-service/order-pagination.html#ordering

https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/entity-service/order-pagination.html#ordering

https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/query-engine/populating.html

0 Answers
Related