Flatten only a particular node?

Following up on this thread: Flattening a particular node?

Is thit possible to flatten only a particular node?

For example, instead of:

{
   "title": "My title",
   "author": {
      "authorId": 42
    },
   "publisher": {
      "publisherId": 28
    }
}

we want to have:

{
   "title": "My title",
   "authorId": 42
   "publisher": {
      "publisherId": 28
    }
}

I don’t know how I could do that with the @normalize directive, which flattens everything under it.

Yeah, you can do

{
  q(func: eq(title, "some title")){
    title
    author @normalize {
      authorId : authorId
    }
    publisher {
      publisherId
    }
  }
}

It would return

{
   "title": "My title",
   "author": [ 
      {
        "authorId": 42
      } 
   ],
   "publisher": {
      "publisherId": 28
    }
}

wouldn’t it?

With GitHub - dgraph-io/flock: Twitter on Dgraph, schema is

<author>: uid @count @reverse .
<created_at>: datetime @index(hour) .
<description>: string .
<dgraph.graphql.schema>: string .
<followers_count>: int .
<friends_count>: int .
<hashtags>: [string] @index(exact) .
<id_str>: string @index(exact) @upsert .
<mention>: [uid] @reverse .
<message>: string .
<profile_banner_url>: string .
<profile_image_url>: string .
<retweet>: bool .
<screen_name>: string @index(term) .
<urls>: [string] .
<user_id>: string @index(exact) @upsert .
<user_name>: string @index(hash) .
<verified>: bool .
type <Tweet> {
	id_str
	created_at
	message
	urls
	hashtags
	author
	mention
	retweet
}
type <User> {
	user_id
	user_name
	screen_name
	description
	friends_count
	followers_count
	verified
	profile_banner_url
	profile_image_url
}

and this query

{ dataquery(func: has(hashtags), first: 10) 
  { 
    created_at: created_at
    author @normalize  {
        authorId: user_id
    }
  }
}

returns

{
  "data": {
    "dataquery": [
      {
        "created_at": "2020-10-04T14:44:46Z",
        "author": [
          {
            "authorId": "16696854"
          }
        ]
      },
      {
        "created_at": "2020-10-04T14:44:46Z",
        "author": [
          {
            "authorId": "705417441686396928"
          }
        ]
      },
...

The same goes for the second example of https://dgraph.io/docs/query-language/normalize-directive/:

This portion of the query:

...
     starring(first: 2) @normalize {
        performance.actor {
          actor: name@en
        }
        performance.character {
          character: name@en
        }
      }
...

returns:

...
      "starring": [
              {
                "actor": "John Michael",
                "character": "Doctor"
              },
              {
                "actor": "Brad Parker",
                "character": "Jim"
              }
            ],
...

if you are looking for a result like:

"author": {
      "authorId": 42
    }

Instead of

"author": [ 
      {
        "authorId": 42
      } 
   ]

Sorry, that won’t work. Dgraph can’t return it as a single object. It will always return in an array response. As it is more likely to have several objects instead of one. Unless you have a 1:1 relation. In that case, it should return a single object.

Cheers.

What about what I described in my initial question? Is there a way to obtain it? With variables maybe?

{
   "title": "My title",
   "authorId": 42
   "publisher": {
      "publisherId": 28
    }
}

Hi @vibl
If you are sure that there is only one author id, then this might work for you:

{
  q as var(func: eq(title, "My title"))   {
    title as title
    author (first:1)    {
      aid as authorId      
    }
    authorIdMax as max(val(aid))
  }
  
  q1(func: uid(q))  {
    title: val(title)
    
    authorId : val(authorIdMax)
  
    publisher {
        publisherId
    }
  }
}

Response

{
  "data": {
    "q1": [
      {
        "title": "My title",
        "authorId": 42,
        "publisher": {
          "publisherId": 28
        }
      }
    ]
  }
}
1 Like

Thank you!

That seems convoluted but if there’s no other way, that’ll do.

Hopefully, there will be a simpler way in the future :slight_smile:

Hi,

this is a problem I had as well, and I’d love to have a “flatten node” dgraph solution.

@anand’s solution won’t work for my use case, as I have multiple nodes returning and my IDs are strings - so aggregation doesn’t work.

What I did: I handle it in the go backend. I take the response and regex it like below, which replaces all occurences and gives the expected result:

var nestedWhateverRegex = regexp.MustCompile(`"author":\{"authorId":"(.*?)"\}`)
fixed := nestedWhateverRegex.ReplaceAll(resp.GetJson(), []byte(`"authorId":"$1"`))

Yes, there’s always the possibility of transforming data after getting the query response.