dgraph-io / dgraph

The high-performance database for modern applications
https://dgraph.io
Other
20.37k stars 1.5k forks source link

[ENHANCEMENT]: Allow array of strings in "GraphQL" variable in DQL #9118

Open amaster507 opened 2 months ago

amaster507 commented 2 months ago

Use case and current behavior

Syntax Examples (using default values):

  • query title($name: string = "Bauman") { ... }
  • query title($age: int = "95") { ... }
  • query title($uids: string = "0x1") { ... }
  • query title($uids: string = "[0x1, 0x2, 0x3]") { ... }. The value of the variable is a quoted array.

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"].

This list syntax only works with uids. I don't even know why the example ["13", "14"] is in the docs because those are not hexidecimal uids, and it just adds confusion thinking this feature is already implemented.

I can do:

const query = `
    query q($uids: string){
        items(func: uid($uids)) {
            uid
            srcId
        }
    }
`;

const req = {
  query,
  variables: {
    "$uids": "[0x9a, 0x9b]",
  }
};

But I can't do:

const query = `
    query q($srcIds: string){
        items(func: eq(srcId, $srcIds)) {
            uid
            srcId
        }
    }
`;

const req = {
  query,
  variables: {
    "$srcIds": "[\"25\", \"26\"]",
  }
};

Alternatively, when I want to query for a list of items not a uid, I have to dynamically build a more complex query and variable list.

// imagine this is a dynamic list from an input
const srcIds = [25, 26];
const varList = srcIds.map((_, i) => `$srcId_${i}`);

const query = `
    query q(${varList.map(var => `${var}: string`).join(", ")}){
        items(func: eq(
            srcId,
            ${varList.join(", ")}
          )
        ) {
            uid
            srcId
        }
    }
`;

const req = {
  query,
  variables: Object.fromEntries(varList.map((var, i) => [var, `${srcIds[i]}`]))
};

Enhancement

It would be nicer to do this:

// imagine this is a dynamic list from an input
const srcIds = [25, 26];

const query = `
    query q($srcIds: string){
        items(func: eq(
            srcId,
            $srcIds
          )
        ) {
            uid
            srcId
        }
    }
`;

const req = {
  query,
  variables: {
    "$srcIds": `[${srcIds.map((id) => `"${id}"`)}]`
  }
};

Solution proposal

No response

Links to Discuss, RFC or previous Issues and PRs

https://discuss.dgraph.io/t/how-to-find-nodes-given-an-array-of-values/3316/7?u=amaster507

Links to examples and research

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

Additional Information

It would be best to support the syntax $srcIds: [string] but for now a quicker fix would just allow an array of strings/ints like the $uids: string accepts.

amaster507 commented 2 months ago

There is a question what to do though if the query actually wants to find a string that is equal to what could be evaulated as an array. That is something that will need to be tested and allow a workaround. I know I used strings to store JSON values in Dgraph, and I am sure others do. What I am not sure though is if anyone is querying with eq on those strings. Maybe the better option would be to add the $srcIds: [string] to not break existing functionality of searching for json like strings with $srcIds: string