Let's say I have 3 collections: Roles, Articles, and Users.
// Users collection
{
slug: "users"
....
fields: [
{
name: "roles"
type: "relationship"
relationTo: "user-roles" // User Roles collection
hasMany: true,
}
]
}
// Articles collection
{
slug: "articles"
....
fields: [
{
name: "whoCanView"
type: "relationship"
relationTo: "user-roles"
hasMany: true,
}
]
}
Now, if the field is string
, then the comparison is relatively easy, as below.
const query = {
whoCanView: {
equals: "user.roles"
}
}
However, I was not able to find a sample for a many-to-many comparison. Even one-to-one (hasMany: false
) fails when the compared fields are of type relationship. I suppose this is because relationships are generic objects, not regular strings. When a request comes in, user.roles
can be read pretty straightforwardly. If there is a way to expose article.whoCanView
without using a query, it would be much easier to implement a custom comparison.
With that said, can someone shed a light on this matter for me? Thanks!
It just came to my mind that I have not updated the solution on this.
When a record hasMany relations, the related objects are referenced by ID. For example, if an article
can be read by front-desk
or management
, then the database is represented as followed.
articleNo1: {
whoCanRead: [
0: "123",
1: "456",
]
}
roles: {
front-desk: {
id: "123"
},
management: {
id: "456"
},
}
Hence comparison should be based on object.id
, not object.otherValue
.
Each query is considered an object itself, we can construct a dynamic query for many-to-many comparisons. Let's have a sample context here:
// read access function
...
const query = {
or: []
}
for (let role of user.roles) {
query.or.push({
recordReadAccess: {
contains: role.id
}
}
}
// In other words, allow read access if the record contains any of the user roles
// => Contains "Management" or "Front-desk"
return query;
Star
Discord
online
Get dedicated engineering support directly from the Payload team.