I just want to know if there’s any difference between the two functions. Which one of these should be preferred?
Thank you
I just want to know if there’s any difference between the two functions. Which one of these should be preferred?
Thank you
Hello @mariusbolik
Services → Reusable functions that are predefined by strapi with some custom business logic (those are usually wrapped around the query functions actually but with some additional custom logic inside them)
Query → Direct query to database
Example of how these are used:
strapi.services.restaurants.find()
, that services will actually call the next code:
find(params, populate) {
return strapi.query('restaurant').find(params, populate);
},
It is calling the strapi.query() inside it. The thing is that you can modify these services and add your own business logic to it, but you can’t modify query() functions.
Take a look at another example that strapi uses:
strapi.services.restaurants.create(restaurantData)
This one will execute a service called create()
async create(data, { files } = {}) {
const validData = await strapi.entityValidator.validateEntity(strapi.models.restaurant, data);
const entry = await strapi.query('restaurant').create(validData);
if (files) {
// automatically uploads the files based on the entry and the model
await strapi.entityService.uploadFiles(entry, files, {
model: 'restaurant',
// if you are using a plugin's model you will have to add the `source` key (source: 'users-permissions')
});
return this.findOne({ id: entry.id });
}
return entry;
},
As you can see, that service uses some additional business logic, not only the query().create()
as in the example with query().find()
As @sunnyson pointed out not really no. The only time it would really be needed to call the service is if you have customized the service in ./api/someModel/services/someModel.js
or if you are building a custom plugin with custom services.
For the most general of use-cases it’s easier and faster to just directly reference the query instead since our default services from the core-api do the following:
module.exports = {
find(params, populate) {
return strapi.query('restaurant').find(params, populate);
},
findOne(params, populate) {
return strapi.query('restaurant').findOne(params, populate);
},
count(params) {
return strapi.query('restaurant').count(params);
},
async create(data, { files } = {}) {
const validData = await strapi.entityValidator.validateEntity(strapi.models.restaurant, data);
const entry = await strapi.query('restaurant').create(validData);
if (files) {
// automatically uploads the files based on the entry and the model
await strapi.entityService.uploadFiles(entry, files, {
model: 'restaurant',
// if you are using a plugin's model you will have to add the `source` key (source: 'users-permissions')
});
return this.findOne({ id: entry.id });
}
return entry;
},
async update(params, data, { files } = {}) {
const validData = await strapi.entityValidator.validateEntityUpdate(
strapi.models.restaurant,
data
);
const entry = await strapi.query('restaurant').update(params, validData);
if (files) {
// automatically uploads the files based on the entry and the model
await strapi.entityService.uploadFiles(entry, files, {
model: 'restaurant',
// if you are using a plugin's model you will have to add the `source` key (source: 'users-permissions')
});
return this.findOne({ id: entry.id });
}
return entry;
},
delete(params) {
return strapi.query('restaurant').delete(params);
},
search(params) {
return strapi.query('restaurant').search(params);
},
countSearch(params) {
return strapi.query('restaurant').countSearch(params);
},
};
From the above examples you can see there is some additional logic on the create
and update
services but none of the others.
@sunnyson @DMehaffy Thank you guys for giving me a better understanding of the functionality of Strapi.
I was about to ask the same thing. The difference I noticed is that a service respects draft system but query doesn’t. Both trigger lifecycles, don’t they? I suspect that default service implementation wraps a query but didn’t have a chance to dig through sources. Can anybody else add to the topic?
@invariant the query is what triggers the lifecycles, do you have some examples of this not working?
@DMehaffy, thanks for confirming. I stick to services, especially because of drafts, so wasn’t sure about queries.