entityService filters with relation data v4

System Information
  • Strapi Version: 4.0.0
  • Operating System: macOS Monterrey
  • Database: Postgres
  • Node Version: 16.13.1
  • NPM Version: 8.1.4
  • Yarn Version:

Is it possible to filter on related data? For example:

// return all articles where I am the author or a reviewer

const user = ctx.state.user;
if (!user) {
  return ctx.badRequest(null, [{ messages: [{ id: 'No authorization header was found' }] }]);
} 


const entries = await strapi.entityService.findMany('api::article.article', {
	populate: ['author', 'reviewers'],
  	filters: {
    $or: [
      {
        author.id: user.id,
      },
      {
		reviewers.user.id: user.id,
      },
    ],  		
  	},
});

I know this code does not work but I have not found any examples of expressing a filter based on related data
thanks!

Answered:

I found an example in the REST api:

I know this is an old post but I wanted to clarify because I was about to ask the same question and didn’t see a specific answer other than the documentation link, which do not mention the combination of filtering and populating.

Filtering related fields does work, but the syntax is a bit different from what the OP assumed. Dont write the property path as string, but write it as a nested object instead.
e.g. author: { id: user.id } instead of author.id: user.id

So, using Query Engine, the code should be like this:

const entries = await strapi.query('api::article.article').findMany({
  populate: ['author', 'reviewers'],
  where: {
    $or: [
      { author: { id: user.id }},
      { reviewers: { user: { id: user.id }}},
    ],      
  },
});

Using Entity Service, the code should be like this:

const entries = await strapi.entityService.findMany('api::article.article', {
  populate: ['author', 'reviewers'],
  filters: {
    $or: [
      { author: { id: user.id }},
      { reviewers: { user: { id: user.id }}},
    ],  		
  },
});

Also, the filtering will work even without specifically populating the relations.

2 Likes

If you want to find entries where a relationship does not exist, this snippet worked for me. (based on @GregorSondermeier)

const findRelationshipNull = async (collection: string, relationship: string) => {
  const strapiApi = `api::${collection}.${collection}`;

  return await strapi.query(strapiApi).findMany({
    populate: [relationship],
    where: {
      $or: [{[relationship]: {id: {$null: true}}}],
    },
  });
};