CMDBuild Forum

REST API and filtering relations

I had done quite a bit for work with the SOAP API a few years ago. Due to a requirements change, I'm trying to reproduce some of that work using REST and have run into a roadblock trying to get relations for a card.

With SOAP, I could easily request the relations for a card with something like: self.client.client.service.getRelationList(domain, className, id). It doesn't appear that there is an equivalent for that in the REST API, so I'm trying to pass filter to the domains/domain/relations/ endpoint. However, when I do that it is causing errors like: "nested exception is org.postgresql.util.PSQLException: ERROR: column SRC._destinationId does not exist\n  Position: 1395","suppressed":[]". Is there an easier way to request the relations for a specific card?

In python, I'm doing something like the following:

<pre>

def getRelations(domain, attribute=None, value=None):

    if attribute and value:

        filter = {'filter': json.dumps({'attribute':{'simple':{'attribute': attribute, 'operator': 'equal', 'value': [ value ]}}})}

        r = requests.get(restBaseURL + 'domains/' + domain + '/relations/', headers=authHeader, params=filter)

    else:

        r = requests.get(restBaseURL + 'domains/' + domain + '/relations/', headers=authHeader)

    if 'data' in r.json():

        rels = r.json()['data']

        if isinstance(rels, list):

            return(rels)

        else:

            return([rels])

    else:

        return([])

</pre>

Which would be called with: getRelations(domain, '_sourceId', cardId)

It always returns an empty list, and if add a "print r.text" to the getRelations() function I can see the huge stack trace with the error I mentioned above. 

Dear Daniel,
If the goal is to have related cards of a specific card you can filter using relation keyword. 
 
This is a filter example to get all cards of class "ClassB" related to the "CardA1" of type "ClassA".
params = {
   "filter":{
      "relation":[
         {
            "destination":"ClassA",
            "direction":"_1",
            "domain":"DomainClassAClassB",
            "source":"ClassB",
            "type":"oneof",
            "cards":[
               {
                  "className":"ClassA",
                  "id":IdCardA1
               }
            ]
         }
      ]
   }
}
r = requests.get(restBaseURL + 'classes/ClassB/cards/', headers=authHeader, params=params)
 
Best regards.
 
-- CMDBuild Team
 
 
Previously Daniel wrote:

I had done quite a bit for work with the SOAP API a few years ago. Due to a requirements change, I'm trying to reproduce some of that work using REST and have run into a roadblock trying to get relations for a card.

With SOAP, I could easily request the relations for a card with something like: self.client.client.service.getRelationList(domain, className, id). It doesn't appear that there is an equivalent for that in the REST API, so I'm trying to pass filter to the domains/domain/relations/ endpoint. However, when I do that it is causing errors like: "nested exception is org.postgresql.util.PSQLException: ERROR: column SRC._destinationId does not exist\n  Position: 1395","suppressed":[]". Is there an easier way to request the relations for a specific card?

In python, I'm doing something like the following:

<pre>

def getRelations(domain, attribute=None, value=None):

    if attribute and value:

        filter = {'filter': json.dumps({'attribute':{'simple':{'attribute': attribute, 'operator': 'equal', 'value': [ value ]}}})}

        r = requests.get(restBaseURL + 'domains/' + domain + '/relations/', headers=authHeader, params=filter)

    else:

        r = requests.get(restBaseURL + 'domains/' + domain + '/relations/', headers=authHeader)

    if 'data' in r.json():

        rels = r.json()['data']

        if isinstance(rels, list):

            return(rels)

        else:

            return([rels])

    else:

        return([])

</pre>

Which would be called with: getRelations(domain, '_sourceId', cardId)

It always returns an empty list, and if add a "print r.text" to the getRelations() function I can see the huge stack trace with the error I mentioned above. 

 

Thanks, that does the trick! What is the syntax for passing filters to the relations method? The one thing I remember quite well from working with the cmdbuild APIs before is that the filters are non-intuitive and there isn't a lot of documentation on them that I can find...
 
Previously Tecnoteca wrote:
Dear Daniel,
If the goal is to have related cards of a specific card you can filter using relation keyword. 
 
This is a filter example to get all cards of class "ClassB" related to the "CardA1" of type "ClassA".
params = {
   "filter":{
      "relation":[
         {
            "destination":"ClassA",
            "direction":"_1",
            "domain":"DomainClassAClassB",
            "source":"ClassB",
            "type":"oneof",
            "cards":[
               {
                  "className":"ClassA",
                  "id":IdCardA1
               }
            ]
         }
      ]
   }
}
r = requests.get(restBaseURL + 'classes/ClassB/cards/', headers=authHeader, params=params)
 
Best regards.
 
-- CMDBuild Team
 
 
Previously Daniel wrote:

I had done quite a bit for work with the SOAP API a few years ago. Due to a requirements change, I'm trying to reproduce some of that work using REST and have run into a roadblock trying to get relations for a card.

With SOAP, I could easily request the relations for a card with something like: self.client.client.service.getRelationList(domain, className, id). It doesn't appear that there is an equivalent for that in the REST API, so I'm trying to pass filter to the domains/domain/relations/ endpoint. However, when I do that it is causing errors like: "nested exception is org.postgresql.util.PSQLException: ERROR: column SRC._destinationId does not exist\n  Position: 1395","suppressed":[]". Is there an easier way to request the relations for a specific card?

In python, I'm doing something like the following:

<pre>

def getRelations(domain, attribute=None, value=None):

    if attribute and value:

        filter = {'filter': json.dumps({'attribute':{'simple':{'attribute': attribute, 'operator': 'equal', 'value': [ value ]}}})}

        r = requests.get(restBaseURL + 'domains/' + domain + '/relations/', headers=authHeader, params=filter)

    else:

        r = requests.get(restBaseURL + 'domains/' + domain + '/relations/', headers=authHeader)

    if 'data' in r.json():

        rels = r.json()['data']

        if isinstance(rels, list):

            return(rels)

        else:

            return([rels])

    else:

        return([])

</pre>

Which would be called with: getRelations(domain, '_sourceId', cardId)

It always returns an empty list, and if add a "print r.text" to the getRelations() function I can see the huge stack trace with the error I mentioned above. 

 

 

I spoke too soon, that only sort-of works.  For example, I have two domains:
ImageDependencies => 1:N Image -> Image
InstanceImage => 1:N Instance -> Image
 
Both of these filters work as expected:
    {'filter': '{"relation": [{"direction": "_1", "destination": "Image", "domain": "ImageDependencies", "source": "Image", "cards": [{"className": "Image", "id": 60288}], "type": "oneof"}]}'}
    {'filter': '{"relation": [{"direction": "_2", "destination": "Image", "domain": "ImageDependencies", "source": "Image", "cards": [{"className": "Image", "id": 60288}], "type": "oneof"}]}'}
Returning the images that 60288 depends on for the former and the images dependent on 60288 for the latter.
 
However, when I attempt to query the InstanceImage relationships I don't get anything back with this filter:
    {'filter': '{"relation": [{"direction": "_1", "destination": "Image", "domain": "InstanceImage", "source": "Instance", "cards": [{"className": "Instance", "id": 100658}], "type": "oneof"}]}'}
 
Looking at the card, that is the correct ID of the Instance and I see the relationship in the web UI. What stupid thing am I doing wrong?
 
Previously Tecnoteca wrote:
Dear Daniel,
If the goal is to have related cards of a specific card you can filter using relation keyword. 
 
This is a filter example to get all cards of class "ClassB" related to the "CardA1" of type "ClassA".
params = {
   "filter":{
      "relation":[
         {
            "destination":"ClassA",
            "direction":"_1",
            "domain":"DomainClassAClassB",
            "source":"ClassB",
            "type":"oneof",
            "cards":[
               {
                  "className":"ClassA",
                  "id":IdCardA1
               }
            ]
         }
      ]
   }
}
r = requests.get(restBaseURL + 'classes/ClassB/cards/', headers=authHeader, params=params)
 
Best regards.
 
-- CMDBuild Team
 
 
Previously Daniel wrote:

I had done quite a bit for work with the SOAP API a few years ago. Due to a requirements change, I'm trying to reproduce some of that work using REST and have run into a roadblock trying to get relations for a card.

With SOAP, I could easily request the relations for a card with something like: self.client.client.service.getRelationList(domain, className, id). It doesn't appear that there is an equivalent for that in the REST API, so I'm trying to pass filter to the domains/domain/relations/ endpoint. However, when I do that it is causing errors like: "nested exception is org.postgresql.util.PSQLException: ERROR: column SRC._destinationId does not exist\n  Position: 1395","suppressed":[]". Is there an easier way to request the relations for a specific card?

In python, I'm doing something like the following:

<pre>

def getRelations(domain, attribute=None, value=None):

    if attribute and value:

        filter = {'filter': json.dumps({'attribute':{'simple':{'attribute': attribute, 'operator': 'equal', 'value': [ value ]}}})}

        r = requests.get(restBaseURL + 'domains/' + domain + '/relations/', headers=authHeader, params=filter)

    else:

        r = requests.get(restBaseURL + 'domains/' + domain + '/relations/', headers=authHeader)

    if 'data' in r.json():

        rels = r.json()['data']

        if isinstance(rels, list):

            return(rels)

        else:

            return([rels])

    else:

        return([])

</pre>

Which would be called with: getRelations(domain, '_sourceId', cardId)

It always returns an empty list, and if add a "print r.text" to the getRelations() function I can see the huge stack trace with the error I mentioned above.