I have a functional query rule that returns the datasubset I am interested in. W

I have a functional query rule that returns the datasubset I am interested in. With the data from that data subset I would like to populate a CDT. Is there a way to convert the data section of a datasubset into a CDT? The syntax I am trying to use:

a!save(ri!CDT_dataWeNeed,fn!index(rule!Database_getData(),"data",""))

The reason I am trying to do this is because I would like to use dot notation to move data from a database with datastore to nested CDTs to create an XML message.

OriginalPostID-164186

OriginalPostID-164186

  Discussion posts and replies are publicly visible

  • Basically, you would use cast() and typeof() cast it to the type of the CDT. Something along the lines of the following will get you what you need:
    cast(
    typeof(
    'type!CDT_YouNeed'()
    ),
    fn!index(rule!Database_getData(),"data",""))
  • Thanks, I will give it a try and see if it saves me any lines of code.
  • 0
    Certified Lead Developer
    There is another silghtly longer-winded way of doing this that supports arrays of data returned by the rule - it might not fit your use case but here it is anyway:

    with(
              local!data: rule!Database_getData(),
              apply(
                        type!CDT_dataWeNeed(
                                  _,
                                  _,
                                  _
                        ),
                        merge(
                                  index(local!data, "id", {}),
                                  index(local!data, "dataField1", {}),
                                  index(local!data, "dataField2", {})
                        )
              )
    )
  • 0
    Certified Lead Developer
    Oops -if your rule returns a dataSubset, then the second line should be: local!data: index(rule!Database_getData(),"data",{}),
  • @philb I guess we can eliminate looping in case of arrays being returned by rule by changing the way we type cast:

    cast(
    typeof(
    {'type!CDT_YouNeed'()}
    ),
    fn!index(rule!Database_getData(),"data",""))

    I tried this approach many times in case of a multiple cdts being returned from datasubset and it worked absolutely fine. Further I also used the same approach to flatten the data sets that were returned from multiple queries.

    To the best of my knowledge, it depends on how we type cast the data, i.e. if it is single, use 'type!CDT_YouNeed'(), and if it is multiple, use {'type!CDT_YouNeed'()}. Please do let me know I missing something.
  • 0
    Certified Lead Developer
    Yep, fair point; as long as the typeof() returns a list of type, the cast() should work correctly. I guess my example maps each of the fields explicitly and so could be used where the rule returns data where the fields are named differently?
  • @philb Correct, should be definitely useful in case when the datasusbet returns data of more than one type which could happen at times.
  • 0
    Certified Associate Developer
    Hello,

    Is there a way to merge two datasubsets on the basis of common value in each of them? for example, Suppose I have a datasubset1 containing the value
    {UserName: "Smith",
    Position: "Manager",
    }

    and datasubset2 contains

    {UserName: "Laura"
    Age : 35
    },
    {UserName: "Smith",
    Age:40
    }

    Now in this case I want the record of "Smith" which is in another datasubset to get appended with the similar value in datasubset1

    i.e My output should be

    {UserName: "Smith"
    Position: "Manager"
    Age:40
    },
    {UserName: "Laura"
    Age: 35 // As there is no common record exist for user "Laura" in another subset.
    }

    Please help me on this. Thanks in advance
  • 0
    Certified Lead Developer
    in reply to viveku3486

    Usually i'd suggest starting a new topic for this question since it doesn't really have much in common with the use case being asked about in the original thread from 2 years ago.

    However I believe I have a workable solution (assuming you're using 17.2 or newer), so here goes:

    with(
      
      local!dataset1: {
        {
          UserName: "Smith",
          Position: "Manager"
        },
        {
          UserName: "Johnson",
          Position: "Cashier"
        },
        {
          UserName: "Apple",
          Position: "Merchandise"
        }
      },
      
      local!dataset2: {
        {
          Name: "Smith",
          Age: 40
        },
        {
          Name: "Johnson",
          Age: 23
        },
        {
          Name: "Baker",
          Age: 54
        }
      },
      
      a!forEach(
        local!dataset1,
        {
          NewDatasetName: fv!item.UserName,
          NewDatasetPosition: fv!item.Position,
          NewDatasetAge: with(
            local!dataset2Index: index(where(local!dataset2.Name = fv!item.UserName), 1, null()),
            if(
              isnull(
                index(
                  local!dataset2.Age,
                  local!dataset2Index,
                  null()
                )
              ),
              "N/A",
              local!dataset2[local!dataset2Index].Age
            )
          )
        }
      )
    )

    Note that this example iterates over "dataset1" and creates a new dictionary for only the entries found in it.  If there are any entries in "dataset2" not mentioned in the other one, they will not be reflected in the new dictionary.

     

    Results:

  • 0
    Certified Associate Developer
    in reply to Mike Schmitt
    Hi Mike,

    Thank you so much for your response. Its working.. Thanks again