Feature: Add foreach() function

diggy
Thu, 30 Apr 2020 02:38:37 +0000
Dgraph

Moved from GitHub dgraph/5335

Posted by MichelDiz:

Experience Report

What you wanted to do

I would like to use loops in queries and upsert blocks. In this case something similar to “foreach”.

What you actually did

There’s nothing similar to this in Dgraph right now.

Why that wasn’t great, with examples

A loop like foreach would be very useful. There are situations that we want to iterate over objects in a query. Whether to display a particular form structure in the response or to create specific mutations in the upsert block. Which is not currently supported in Dgraph.

Syntax

I believe that Syntax from foreach would be very similar to the K-shortest path.

More examples

I think a “foreach” func would be the solution for almost all the things like “groupby value”.

Ref of a DB doing something similar to it:

Neo4j Graph Data Platform

FOREACH - Cypher Manual

The `FOREACH` clause is used to update data within a collection whether components of a path, or result of aggregation.

mongodb.com

cursor.forEach() (mongosh method) - Database Manual - MongoDB Docs

Iterate over documents in a MongoDB cursor using `forEach()` to apply a JavaScript function to each document.

A foreach loop could solve this issue #4779 in a blink of an eye (eliminating the misuse of an extra block). I gonna add a comment there with an example using “foreach”.

see Bug with multi-level (nested bocks) in Upsert Block · Issue #4779 · dgraph-io/dgraph · GitHub

In this link FOREACH func in DQL (loops in Bulk Upsert) - Dev - Discuss Dgraph I have other use cases. Most of them related to upsert block, issues with Facets bad responses (e.g: #4160), and so on.

Pay attention that this link is a little old. I used different syntax just to illustrate.

Reference for the group by issue: Groupby does not support predicate of list type · Issue #4170 · dgraph-io/dgraph · GitHub

e.g: “for each group found in groupby create a new object to use in response”.

foreach(in: PARAM1, title: PARAM2).

> For each UID in PARAM1, create a new object in the response with the title in PARAM2

{
 var(func: has(kind)) @groupby(kind) {
    T as count(uid)
  }

 foreach(func: foreach(in: T, title: kind)) {
   name
   age
   total : val(T)
 }
}

Desirable Result

{
  "data": {
    "q": [
      {
        "dog": [
              {
                "total": 1
              },
              {
                "uid": "0x1",
                "name": "Bingo",
                "age": "3"
              }
      ]
      },
      {
        "animal": [
              {
                "total": 2
              },
              {
                "uid": "0x1",
                "name": "Bingo",
                "age": "3"
              },
              {
                "uid": "0x3",
                "name": "Angry Purr",
                "age": "1"
              }
      ]
      },
      {
        "cat": [
              {
                "total": 1
              },
              {
                "uid": "0x3",
                "name": "Angry Purr",
                "age": "1"
              }
      ]
      }
    ]
  }

Any external references to support your case

Discuss Dgraph – 27 Nov 19

FOREACH func in DQL (loops in Bulk Upsert)

Dev

proposal discussion

Ref of a DB doing something similar to it: Before starting see an example in the next comment block. Example with Bulk Upsert upsert { query { source as var(func: has(linkto)) { v0 as uid LK as linkto } LINK as...

Reading time: 2 mins 🕑 Likes: 1 ❤

7 posts - 4 participants