Strapi V4 search by slug instead ID

Greetings,

I have a question regarding findOne method. I would like to search by SLUG instead default ID. Do you have any ideas on how to implement this scenario? I have searched the docs, but there is a manual for V3 of Strapi.

Thanks for your answers. This topic is quite crucial and many users will find it usefull.

2 Likes

I agree, this would be very helpful to a lot of users. I understand that v4 is really new and writing new documentation takes time, but I think it’s a bit premature making v4 the default and not having all the docs fully ready.

2 Likes

Hi,

Updating because I just found it:

http://localhost:1337/api/your-content-type-plural?filters[your-slug-field-name][operator]=your-slug-goes-here
# In my case:
http://localhost:1337/api/posts?filters[slug][$eq]=entrada-de-prueba-2

Source: REST API - Strapi Developer Docs

2 Likes

@Myddna this works but you are using find() method, not findOne() and they behave differently.

For example if post with slug does not exists you still get 200 response with this approach, while with findOne (when providing id) you would get 404.

You will get a 200 res, but no data… you can just validate if data is present on the front-end. I’d also use the same method for findOne, even if the id is ok but no content is returned I would treat it as a 404.

You can override this controller action in order to do so.
At least in version 3.6 which I have used widely so it worked.
To do so you must go in api/articles/controllers/articles.js

Check below link, maybe it still works same (similar)

I did try to modify the example to override controller but with no success.

I don’t know how to pass slug to await strapi.service('api::restaurant.restaurant').findOne(id, query); ?

Working now for me after following the docs Myddna linked and querying for /api/your-content-type?filters[slug][operator]=your-slug-string. You do recieve a status 200 though but for me using Next.js with getStaticPaths I manage to recieve 404 responses for pages not defined in the paths.

1 Like

Thank you for this!!! Everything on the Internet is showing Strapi 3 examples.

DOES NOT WORK: http://localhost:1337/posts?slug=${slug}

WORKS: http://localhost:1337/api/posts?filters[slug][$eq]=S-L-U-G

@Strapy you need to update documentation and examples for basic things ASAP.

Hi, you can redefine your findOne method in your controller.
You cannot find by id when did this change
That is an example of your redefined findOneMethod

module.exports = createCoreController('api::product.product', ({ strapi }) =>  ({
  async findOne(ctx) {
    const { id: slug } = ctx.params;
    const { query } = ctx;
    if (!query.filters) query.filters = {}
    query.filters.slug = { '$eq': slug }
    const entity = await strapi.service('api::product.product').find(query);
    const { results } = await this.sanitizeOutput(entity, ctx);

    return this.transformResponse(results[0]);
  }
}))

Other option is to create a custom route like /api/products/product/:slug and use it instead of override the strapi one, you mantain twice with this option