cancel
Showing results for 
Search instead for 
Did you mean: 

Compositions and CQL in Node.JS

Steven_UM
Contributor
368

Hi,

I started using compositions in favor of associations as per the CDS documentation recommendations.

That works fine - model is converted into DB tables etc.

Now I seem to face an issue when trying to address those compositions within node.js using CQL.

Here is a simplified version of my entity

entity Campaigns: cuid, managed {  
<xxx>
@cds.autoexpose
Steps: Composition of many CampaignStep;
}
aspect CampaignStep ...

Now I want to use the entity and its underlying 'step' in coding ... so basically well also as an entity as I want to write specific CQL on those 'Steps'. Easy with associations. Not so with compositions it seems.

Naturally I tried

const { Campaigns,  CampaignsSteps } = cds.entities("xxx");

Does not work as 'CampaignsSteps' is not a 'real' entity I suppose. Fair enough.

Ok let's try writing some CQL then on 'Campaigns' assuming we can reference 'Steps' somehow.

let q1 = SELECT.from(Campaigns.Steps).columns(...

Huray. Syntax ok and CDS runs.

Until it is executed. I am getting an exception telling me 'not an entity, table or ...'.

Ok another attempt then.

let q1 = SELECT.from(Campaigns.compositions.steps).columns(...

Huray again. Syntax ok and CDS runs.

Until it is executed. Now I am getting a more interesting error. It tells me that 'the table or view does not exist'. Which is correct as it somehow managed to reference the correct table name but with the wrong namespace. It is not at all using the namespace of the main entity declaration but - if I would guess - just takes the first alphabetical ordered namespace existing in my project. So it tries to read from a table that indeed does not exist in my DB.

In the end I got it working using - a hack as far as I am concerned:
let q1 = SELECT.from(Campaigns.compositions.steps.target).columns(...

The target attribute seems to hold a string having the 'correct full table name including the correct namespace' so hence that works 'by accident'.This stops working then if you have a composition within a composition, etc.Maybe I am overlooking something obvious but there should be a better way of doing this ?I am very much starting to doubt on whether I continue with compositions. They might seem fine if you have some basic 'out of the box' ODATA service but once you start coding it gets messy it seems. I simply want to reference the compositions as 'entities' I guess.Thanks,Steven
patricebender
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi Steven,

I am not an expert on how the runtime handles navigating along the compositions in a CQL statement. Under the hood - for a composition of aspects - a table is created with an identifier like <entity>_<composition>, so in your case the table's name will be Campaigns_Steps. Maybe you could try:

let q1 = SELECT.from(Campaigns_Steps).columns(...

Let me know if this works.

Best Regards,

Patrice

Steven_UM
Contributor
0 Kudos

Hi patricetao,

Thanks for your response.

Unfortunately your suggestions doesn't work ... "undefined".

// Entities
const { Campaigns, Campaigns_Steps } = cds.entities("xxx");

I think I tried importing any possible upper/lower case with and without '_' I could think off ... nothing works I am afraid.

Kind Regards,

Steven

Accepted Solutions (0)

Answers (1)

Answers (1)

patricebender
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi Steven,

I made it work with:

const query = await SELECT.from({ref: [{id:"Campaign.Steps"},'composition']});

You could now also apply some filter-conditions. For example, I was able to fetch all German books from the localized "books.texts" table of the famous Bookshop sample with:

const query = await SELECT.from({ref: [{id:"Books.texts", where: [{ref:['locale']},'=',{val:'de'}]},'composition']});

Hope this helps you,

Patrice

Steven_UM
Contributor

Thanks Patrice for finding alternative ways for declaring this.

A couple of alternative solutions exist but none of them have of course the 'elegance' of just declaring the composing as an entity reference - which seems to me to be the whole point of using CQL - easyness & elegance.

Btw ... I dropped the compositions and reverted back to associations in my data model.

I encountered numerous other issues when trying to use them them in ODATA services etc ... all too much issues and not worth my time.

Thanks for your efforts though,

Steven