strapi

How to get random records from Strapi content API


I have records in strapi. I am using strapi content API. In my front-end, I need to display only 2 records randomly. For limiting, I have used limit query from content API. But random fetching what keyword I need to use. The official documentation doesn't provide any details regarding this - https://strapi.io/documentation/v3.x/content-api/parameters.html#available-operators


Solution

  • Randomize at Data Layer

    There's no official Strapi API feature for random. You have to implement yourself, likely in the form of a Strapi service.

    Please scrutinize all posted solutions. Also, with Strapi v4 and v5, AFAIK you still have to handle randomization yourself but there are newer features that may make this all easier.

    Low-level, data layer solution

    Below is what I've done previously, using Strapi v3. It affects the data query directly, but therefore it negates Strapi abstraction (the point of using Strapi). For the project, I had other reasons to make a raw query.

    Alternatively, other posted solutions use the HTTP API, which has benefits too, but rely on network requests.

    1 - Make a service function

    File: api/mymodel/services/mymodel.js

    This will contain our actual random query (SQL), and wrapping it in a service is handy because it can be used in many places (cron jobs, inside other models, etc).

    module.exports = {
        serviceGetRandom() {
    
            return new Promise( (resolve, reject) => {
                
                // There's a few ways to query data.
                // This example uses Knex.
    
                const knex = strapi.connections.default
                let query = knex('mydatatable')
    
                // Add more .select()'s if you want other fields
                query.select('id')
    
                // RANDOMIZATION HERE: These rules enable us to get one random post
                query.orderByRaw('RAND()')
                query.limit(1)
    
                // Initiate the query and do stuff
                query
                .then(record => {
                    console.log("getRandom() record: %O", record[0])
                    resolve(record[0])
                })
                .catch(error => {
                    reject(error)
                })
            })
        }
    }
    

    2 - Use the service somewhere, like a controller:

    File: api/mymodel/controllers/mymodel.js

    module.exports = {
    
        //(untested)
    
        getRandom: async (ctx) => {
    
            await strapi.services.mymodel.serviceGetRandom()
            .then(output => {
                console.log("getRandom output is %O", output.id)
                ctx.send({
                    randomPost: output
                }, 200)
            })
            .catch( () => {
                ctx.send({
                    message: 'Oops! Some error message'
                }, 204) // Place a proper error code here
            })
    
        }
    
    }
    

    3 - Create a route that points to this controller

    File: api/mymodel/config/routes.json

    ...
        {
            "method": "GET",
            "path": "/mymodelrandom",
            "handler": "mymodel.getRandom",
            "config": {
                "policies": []
            }
        },
    ...
    

    4 - In your front-end, access the route

    (However you access your API)

    e.g. ajax call to /api/mymodelrandom