Support lists in query variables (Dgraph's GraphQL Variable)

Moved from GitHub dgraph/2726

Posted by F21:

Experience Report

I often have queries where I want to match a list of things (similar to an IN query in SQL). For example:

{
  someQuery(func: eq(somePredicate, val1, val2){
    someField
  }
}

Often, these values come from user input and I want to pass these values to the query using query variables.

Effectively, this would allow a query like so:

query($vals: []string){
  someQuery(func: eq(somePredicate, $vals){
    someField
  }
}

What you wanted to do

I wanted to pass a list of values as a query variable into a query.

What you actually did

I had to create the query programmatically using string concatenation.

Why that wasn’t great, with examples

Having to use string concatenation introduced a lot of noise into the code and the query was very unreadable.

Any external references to support your case

None.

1 Like

MichelDiz commented :

Note: This seems duplicated of https://github.com/dgraph-io/dgraph/issues/2272
PS. Just a note.

MichelDiz commented :

Hey @F21 , I gonna close this issue due duplicate. To keep just one issue tracking this, the 2272.

Anyway thanks for the care of having opened an issue for this.

Cheers.

MichelDiz commented :

Well I’m reopening this due some changes and more info related to GraphQL standard.

The issue #2272 was solved, but it was specific for block arrays, with an example of payload
with array. But it did not go deep into adding an array to the var type itself.

Now I see that this issue appears to be more specific for this case.

As Dgraph intends to get closer to GraphQL’s standard. I believe this is a good feature for this.
In GraphQL you can add arrays to the variables used in a Query. e.g:

{
  query: `
    query events ($containsId: [Int]) { 
     # the parse results  events(containsId: [1,2,3]) {
      events(containsId: $containsId) {
        id
        name
      }
    }
  `,
  variables: {
    containsId: [1,2,3]
  }
}

UPDATE:

Also there’s an issue with Documentation that says about the possibility to use arrays for UID.

Check https://docs.dgraph.io/query-language/#graphql-variables

Testing in https://play.dgraph.io/ I can’t put a list of UIDs to work as docs says.

Note If you want to input a list of uids as a GraphQL variable value, you can have the variable as string type and have the value surrounded by square brackets like [“13”, “14”].

I’ve tested several combinations and none was successful as docs mention.

query q($name1:string = ["0x1878bd", "0x237702"]) {
   me(func: uid( $name1 )) {
    uid
    name@en
    director.film @filter(lt(initial_release_date, "1980-01-01"))  {
      initial_release_date
      name@en
    }
  }
}

“0x1878bd, 0x237702” are “Ridley Scott” and “Steven Spielberg” uids.

srfrog commented :

This is similar to #2272 but it’s in fact a different feature. The variable array (Gql) is not the same as the argument list. We would need to add support for arrays and convert them into argument list for this to work.

The uid list is not the same as the array in the variable. This is how it works:

{
   //            .... argument list ....
   me(func: uid( "0x1878bd", "0x237702" )) {
    uid
    name@en
    director.film @filter(lt(initial_release_date, "1980-01-01"))  {
      initial_release_date
      name@en
    }
  }
}

MichelDiz commented :

The uid list is not the same as the array in the variable.

Yeah, I know. But the point is that the Docs indicates that it is possible to use array for UIDs with Graphql Vars. I have not found any way to make it work according to the “Note” from docs.

d4l3k commented :

Any update on this? I’d really like to be able to do

query docs($urls: [string]) {
  docs(func: eq(url, $urls)) {
    title
    desc
  }
}

but it sounds like it’s not currently supported. Coming from the SQL world this seems like a very basic operation that should be supported.

Sceat commented :

A year passed, any update on array support ? the current workaround is to use string interpolation in the client code

sanan-fataliyev commented :

+1

ahctangU commented :

Is there ever any plan to support this? Otherwise, I have to do a string replacement for my query…

MichelDiz commented :

Please, vote for the issue. We like comments when they add use cases. If you are just “voting” please, thumbs up the issue itself.

PS. Nothing is decided yet.

dpkirchner commented :

Until this is done, would you mind updating the docs here to say it’s not possible: https://dgraph.io/docs/query-language/#uid ? I just bumped in to this issue as well.

MichelDiz commented :

@dpkirchner not sure what you mean. This part of the docs isn’t related to GraphQL Variables.

dpkirchner commented :

@MichelDiz Sounds like I’m just confused. There’s GraphQL variable queries and there’s regular queries that look pretty similar, and you can’t pass multiple GraphQL variables to uid() (you’ll see “Only one GraphQL variable allowed inside uid function” which I include here as google bait).

I see now in the docs you linked: “Note If you want to input a list of uids as a GraphQL variable value, you can have the variable as string type and have the value surrounded by square brackets like [“13”, “14”].” That’s not exactly how it seems to work in my tests, at least when using dgraph-js. The way to query multiple uids is to concatenate an array of the hex uids into a single string that is wrapped with square brackets, like so:

query query($uids: string) {
  query(func: uid($uids)) {
    ...
  }
}
txn.queryWithVars(query, {vars: {
  $uids: '[' + uids.join(',') + ']'
}});

ultimately, $uids = '[0x123,0x456,0x789]' (no quotes in the array string, hex values).

I don’t know what’s really actionable here beyond, maybe, updating the “Note if you want …” text.

MichelDiz commented :

This works

query query($uids: string = "[0x1, 0x2, 0x3]") {
  query(func: uid($uids)) {
    uid
  }
}

so, what needs to change, and not confuse future users, is the uid part. I gonna add references about this there.

vancouverwill commented :

This works

query query($uids: string = "[0x1, 0x2, 0x3]") {
  query(func: uid($uids)) {
    uid
  }
}

so, what needs to change, and not confuse future users, is the uid part. I gonna add references about this there.

that’s a nice interim solution but the client shouldn’t have to convert a list of uids to strings and concatenate, we should be able to have an input of type [string] or [uid]

MichelDiz commented :

@vancouverwill that’s still the objective of this issue. I was just trying to help dpkirchner. I have done the change in docs about this. Until we have list support on GraphQL Variables.

vancouverwill commented :

@vancouverwill that’s still the objective of this issue. I was just trying to help dpkirchner. I have done the change in docs about this. Until we have list support on GraphQL Variables.

great, thankyou