How do I write a read-model/postgraphile query for a Map field in a protocol?
e.g.
protocol[admin, customer] Project() {
...
var projectLog: Map<ProjectLog, Set<ProjectLogEntry>> = mapOf<ProjectLog, Set<ProjectLogEntry>>();
...
}
where ProjectLog is an enum and ProjectLogEntry is a Struct.
Milos
October 21, 2024, 11:06am
2
What kind of query are you trying to write? Query by the key (enum) and get back the struct?
I’ll attach my latest query and response. I’m trying to see the contents of projectLog.
It seems I can attach a picture but not a file
Graphql request:
{
protocolStates(
filter: {
protoRefId: { equalTo: "/inv-2.0.1?/investerra/Project" }
protocolId: { in: ["914915ef-dac5-4c37-9c10-c727781ce36b"] }
}
) {
totalCount
nodes {
protocolId
currentState
protocolFieldsProtocolsByProtocolId {
nodes {
field
value
}
}
protocolFieldsStructsByProtocolId {
nodes {
field
value
}
}
protocolFieldsCollectionsProtocolsByProtocolId {
nodes {
field
value
collectionType
}
}
protocolFieldsCollectionsProtocolsByValue {
nodes {
field
value
collectionType
}
}
protocolFieldsCollectionsTextsByProtocolId {
nodes {
field
value
collectionType
}
}
protocolFieldsCollectionsEnumsByProtocolId {
nodes {
field
value
collectionType
}
}
# frame
}
}
}
GraphQL response:
{
"data": {
"protocolStates": {
"totalCount": 1,
"nodes": [
{
"protocolId": "914915ef...",
"currentState": "questionaireSubmitted",
"protocolFieldsProtocolsByProtocolId": {
"nodes": [
{
"field": "creditCheck",
"value": "eec0b865..."
},
{
"field": "user",
"value": "e1a95ad3..."
}
]
},
"protocolFieldsStructsByProtocolId": {
"nodes": [
{
"field": "fourEyeCheck",
"value": "c9441f38..."
},
{
"field": "offerUrl",
"value": "39b7f68d..."
}
]
},
"protocolFieldsCollectionsProtocolsByProtocolId": {
"nodes": []
},
"protocolFieldsCollectionsTextsByProtocolId": {
"nodes": []
},
"protocolFieldsCollectionsEnumsByProtocolId": {
"nodes": [
{
"field": "productTypes",
"value": "INVESTERRA_ELECTRICITY_SALES",
"collectionType": "List</inv-2.0.1?/support/ProductType>"
},
{
"field": "productTypes",
"value": "STORAGE_SOLUTION",
"collectionType": "List</inv-2.0.1?/support/ProductType>"
}
]
}
}
]
}
}
}
jean
October 22, 2024, 11:46am
4
Hi @Stuart_Shannon
For now the read model supports only selected types, and complex types such as nested structs or nested collection are not supported.
We post about this on the Read Model > Known Shortcoming page:
Similarly, it is not possible to query nested collections. We only support querying collection elements on the top level of protocols (hence collections that are nested within structs or other collections are not queryable)
Here are two alternative solutions I can suggest:
the modification the NPL modelling in your application, such that the Set< ProjectLogEntry> is stored in a protocol AND ProjectLogEntry is transformed from a struct to a protocol, or
using the NPL API to retrieve that complex data structure protocol by protocol
I understand the additional complexity in both cases and hope it is suitable for your use-case.
I will ensure this use-case is taken into roadmap discussions and will come back to you down the road when we have a better solution.
Thanks @jean , I thought it would be something like this. A Map is typically not considered a collection type - but I guess it applies to Maps too.
Then my question changes slightly to - How can I query for the contents of a simple Map via the read-model?
e.g. say the Map was:
protocol[admin, customer] Project() {
...
var projectLog: Map<Text, Text> = mapOf<Text, Text>();
...
}
Is the query this?
{
protocolStates(
filter: {
protoRefId: { equalTo: "/inv-2.0.1?/investerra/Project" }
protocolId: { in: ["1284hrnf9-dac5-4c37-9c10-c727738ehdk45"] }
}
) {
totalCount
nodes {
protocolId
currentState
protocolFieldsCollectionsTextsByProtocolId {
nodes {
field
value
collectionType
}
}
}
}
}
There is no protocolFieldsMaps... term as far as I can see.
jean
October 24, 2024, 6:57am
6
Hi @Stuart_Shannon
I modified the IOU protocol to have two maps:
protocol[issuer, payee] Iou(var description: Text, var forAmount: Number) {
var myTextMap: Map<Text, Text> = mapOf<Text, Text>(Pair("foo", "bar"));
var myNumberMap: Map<Text, Number> = mapOf<Text, Number>(Pair("toto", 42));
The query to retrieve the maps is:
{
protocolStates{
totalCount
nodes {
protocolId
protocolFieldsCollectionsTextsByProtocolId {
nodes {
key
value
field
}
}
protocolFieldsCollectionsNumbersByProtocolId {
nodes {
key
value
field
}
}
protoRefId
}
}
}
with the answer looking like
{
"data": {
"protocolStates": {
"totalCount": 1,
"nodes": [
{
"protocolId": "cb244cd3-f61a-4dfb-a09d-e6bde5b8d3b4",
"protocolFieldsCollectionsTextsByProtocolId": {
"nodes": [
{
"key": "foo",
"value": "bar",
"field": "myTextMap"
}
]
},
"protocolFieldsCollectionsNumbersByProtocolId": {
"nodes": [
{
"key": "toto",
"value": "42",
"field": "myNumberMap"
}
]
},
"protoRefId": "/nplintegrations-1.0?/iou/Iou"
}
]
}
}
}
Hope this helps!
1 Like
Thanks @jean
To summarise, to query a Map you need to use:
protocolFieldsCollections<ValueType>ByProtocolId
where ValueType is the type of the value in your Map.
Unfortunately, I think you will also get back Sets and Lists of this type, so parsing is gonna be a bit tricky.
jean
October 24, 2024, 8:55am
8
The collectionType identifier will indicate the original NPL type
{
protocolStates{
totalCount
nodes {
protocolId
protocolFieldsCollectionsTextsByProtocolId {
nodes {
key
value
field
collectionType
}
}
protocolFieldsCollectionsNumbersByProtocolId {
nodes {
key
value
field
collectionType
}
}
protoRefId
}
}
}