What I try to achieve:
Every record can have multiple user types (be shown for different user types).
I want to filter out records, which donât have a current userâs type (donât show a record for a user if itâs not supposed to be shown for this type of a user)
What I did:
I added a new JSON âuserTypesâ field to my schema. So now I have a nicely defined array of values that a content maker can use to specify user types. It results in an array of user types in the gql response.
Problem:
JSON field supports only the exists filtering. But Iâd like to have something like this:
Welcome to the forum, and thank you for the question!
Just to be sure I understand what youâre asking for, could you please explain your use case here a bit better? Who are the âusersâ â are they editors (collaborators) in your DatoCMS project, or unrelated users that youâre syncing in from some external source?
If youâre trying to limit record visibility by DatoCMS user, I think a cleaner & safer way to approach this would be to use our roles & permissions system and create a separate model for each set of users. They can have the same or similar schema, but you can then limit each model to only be viewable by certain user types/roles.
If this filtering has nothing to do with your DatoCMS collaborators and userTypes is just an arbitrary field, we unfortunately donât offer serverside deep-filtering of JSON fields right now. A few workarounds:
Instead of an array of strings, you can make a separate model for âuserTypesâ and use a multi-link field instead. This would overall be safer anyway since you can link to specific userType record by internal UUID rather than a hardcoded user-facing string. You do get back an array of values (their UUIDs), but you can pretty easily look up their other values (like the userType label) if you need to.
You can filter userTypes on the clientside (i.e., download all records and then filter them locally in JS)
You can use the computed fields plugin or a webhook or an API call to mirror the JSON array into a single-line string value, and then do a regex pattern filter on that single-line string⌠but thatâs a hack.
Personally I think the first option (making a separate âuserTypesâ model with its own records) would be the cleanest. Would that work for you?
Yes, âuserTypeâ is just an arbitrary value. You can think of it as a âtag systemâ. I have many records, every record has one or more tags. User may provide a list of tags, and I need to filter records which contain at least one tag from the provided list.
The âmodelâ approach sounds good, but I canât make it work.
In the âSchema â Modelsâ section I created a separate model âaudienceâ, which has a âsingle-line stringâ property. This property has a âSelect inputâ with 4 values (âUSER_TYPE_Aâ, âUSER_TYPE_Bâ, âUSER_TYPE_Câ, âUSER_TYPE_Dâ).
Based on the model I have created 4 records (for each value).
I added a âMultiple Linkâ property - reference to this model.
Now I try to query and filter, but here I face a problem.
My query looks like this:
query {
allItems {
_firstPublishedAt
title
audienceref {
__typename
id
audience
}
}
}
Here Iâm interested in the âaudiencerefâ field. In the response it looks like:
Sorry for not being clearer about this. If you donât want to filter by ID but by the value of a string in the audience model, you have to use our Inverse Relationships feature instead. Youâd look up âall audience records with the field value of ____, and give me the related itemsâ.
You probably also donât need the audience field to be dropdown; each one can just be a unique string.
I sent you an invite to an example project so you can better see how it could work.
To explainâŚ
The Audience model consists of a 4 separate records, each with a single-line string field:
query MyQuery {
# note that you're NOT filtering on `allItems` but on `allAudiences`... THEN getting related items
filteredByInverseRelationship: allAudiences(filter: {name: {in: ["USER_TYPE_B", "USER_TYPE_C"]}}) {
_allReferencingItems {
...ItemFragment
}
}
}
fragment ItemFragment on ItemRecord {
title
audienceref {
name
id
}
}