How to find nodes given an array of values

Is it possible to find all nodes matching a value within an array in a single query?

For example, say our database contains nodes representing a business’ clients with properties name and email. We want to send an email to a set of clients with a personalized header: “Hello {name}!”.

If we already have the emails in an array, how would we go about creating a query that retrieves all the names?

Particularly, sample code using dgraph-js would be great.

1 Like

UPDATE(2020): if you are reading this. Take into account that Dgraph has changed a lot since this post. Some answers and tips here are just examples. For sure you can do the same thing mentioned here in the comments in other ways. For example, a list of strings can be passed via DQL Variable(which was called “graphql variable” back then). You can pass a list of string-like $mylist='[loren, lorem, loren]' and this will be accepted in the DQL variable as a list of args.

This question is somewhat ambiguous, could not understand well.

If you want to find several nodes matching to single value. This is a simple query. You can mix with Has, regexp, Inequality, Connectives (AND, OR and NOT) and so on.
e.g:

{
  names(func: has(email)) @filter(regexp(email /@some.com/i)) {
    name
    email
  }
}

You gonna have an array.

In the query ask for the email and the name at the same time. Otherwise you will make several queries later (or a great extra).

Dgraph generally only delivers an array of requested nodes (per query and/or query block). All work of treatment of the result has to be done via application. Some things can be done with Dgraph, but you need to understand the whole language “GraphQL + -”.

Check One JS example with Dgraph-js for beginners. Using graphQL instead of REST
There are two examples to which you can get what you need.

Cheers.

Hi Michel, thanks for the answer. I’ll try to clarify what I’m trying to achieve.

I have an array with many emails,

[e1@domain1.com, e2@domain2.com, ..., eN@domainN.com]

Is it possible to retrieve the names of all these users in a single query? Or do I need N queries?

Yes, build your query to englobe your array.

As you can see in the documentation of inequality you have a syntax option with array.

  • eq(predicate, [val1, val2, ..., valN])

e.g:

{
  me(func: eq(predicate, [val1, val2, ..., valN])) {
    name@en
    genre {
    	name@en
    }
  }
}

or in JS


const many_emails = [e1@domain1.com, e2@domain2.com, ..., eN@domainN.com]

const query = `
    {
  me(func: eq(predicate, ${many_ emails})) {
    name@en
    genre {
    	name@en
    }
  }
}
       `;
3 Likes

Hi Michel, thanks for the quick answer. That’s just what I was looking for :slight_smile: Thanks!

1 Like

After having implemented your suggestion, I have three follow up questions:

  • Can an array be used with transaction.queryWithVars()?
  • If so, what would be the type that we would supply to the query below?
query allNames($emails: ???) {
  allNames(func: eq(name, $emails) {
    name
  }
}
  • What are the advantages of using queryWithVars() over template string variables?

Thanks for your help Michel

Nop, This is a specification for GraphQL Variables. There is no array for GQL Variables. Check https://graphql.org/learn/queries/#variables You use ES6 template Strings is the most recommended.

ref: Get started with Dgraph

Backward compatibility with GraphQL only.

Cheers.

1 Like

Hi Michel,

I’m trying to do a similar thing using the Python client pydgraph that you demonstrated in a previous JS code snippet but running into an unexpected result/error.

Your JS snippet:

const many_emails = [e1@domain1.com, e2@domain2.com, ..., eN@domainN.com]

const query = `
    {
  me(func: eq(predicate, ${many_ emails})) {
    name@en
    genre {
    	name@en
    }
  }
}

What I’m trying using pydgraph:

    query = """query all($a: string) {
                all(func: eq(samplePred, $a)) {
                        uid
                    }
                }
            """

    variables = {'$a': '["val1", "val2"]'}

    res = client.txn(read_only=True).query(query, variables=variables)

When the query is executed, the following exception is thrown:

'Traceback (most recent call last):\n  File "../.vscode/extensions/ms-python.python-2020.11.371526539/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_resolver.py", line 193, in _get_py_dictionary\n    attr = getattr(var, name)\nAttributeError: Extensions\n'

Am I doing something wrong? I have success writing the same exact query without the use of variables (also tested using ratel UI) but that doesn’t satisfy my use case where the values I’m passing to the eq function are dynamic and passed in as an argument to a function.

Working without the use of a graphql variable

    query = """query all() {
                all(func: eq(samplePred, ["val1", "val2"])) {
                        uid
                    }
                }
            """
    res = client.txn(read_only=True).query(query)

Using v20.7.0 of pydgraph

Sorry for the late reply.

As I’m not a Py dev, I’m not sure how to help. For sure there is something similar to ES6’s Template Strings in Python context.

I see that you are using DQL Variables, that should work, and looks it would work. Have you solved your issue?