What was the rationale behind not allowing maps as field values in query responses?

i.e. Why does Dgraph only give responses like

{
  "data": {
    "user": [
      {
        "uid": "0x5c1c",
        "settings": [
          {
            "account": [
              {
                "email": "me@test.com"
              }
            ]
          }
        ]
      }
    ]
  },
  "extensions": {
    "server_latency": {
      "parsing_ns": 24104,
      "processing_ns": 4277851,
      "encoding_ns": 12867,
      "assign_timestamp_ns": 537711
    },
    "txn": {
      "start_ts": 103396
    }
  }
}

instead of having the option to get responses like

{
  "data": {
    "user": {
			"uid": "0x5c1c",
			"settings": {
				"account": {
					"email": "me@test.com"
				}
			}
		}
  },
  "extensions": {
    "server_latency": {
      "parsing_ns": 24104,
      "processing_ns": 4277851,
      "encoding_ns": 12867,
      "assign_timestamp_ns": 537711
    },
    "txn": {
      "start_ts": 103396
    }
  }
}

If I want to get a user’s email, I have to do res.data.user[0].settings[0].account[0].email, but ideally, I’d like to do res.data.user.settings.account.email. Or does Dgraph already have a feature that I’m not aware of that allows me to get a response like the latter example?

The @normalize directive may help here https://docs.dgraph.io/query-language/#normalize-directive

@amanmangal The @normalize directive still returns the predicate it is applied to as a json array while the elements are flattened. My friend still needs to preserve the json object nesting structure, instead asking for ways to automatically unbox one-element arrays returned by dQuery.

Correct me if I’m wrong, but the @normalize directive only flattens predicates - not arrays. The query for the original example was

{
  user(func: uid(0xabcd)) {
    uid
    settings {
      account {
        email
      }
    }
  }
}

and I’ve tried putting (first: 1) and/or @normalize in different parts of query, but either got invalid query errors or data that is not in the correct shape. How would you modify this query to get the data in a shape where data.user, data.user.settings, and data.user.settings.account are all objects (and NOT arrays)?

Did you try uid instead of [uid] schema? In 1.1 it should give you the behaviour you need. This returns a json object, not a json array and can be accessed using dot notation
Before 1.1 it is not possible afaik since all uid relations were 1-many

Thanks, that solved part of the puzzle. The only place where I could find that in the docs was here: https://docs.dgraph.io/howto/#schema-types-scalar-uid-and-list-uid.

I changed part of my schema from this

settings: [uid] @reverse .
account: [uid] @reverse .

to this

settings: uid @reverse .
account: uid @reverse .

and when I run the same query, I get

  "data": {
    "user": [
      {
        "uid": "0x5dba",
        "settings": {
          "account": {
            "email": "me@test.com"
          }
        }
      }
    ]
  }

So now the questions are

  1. how do I get "user" to be an object (user: uid . did not work)?
  2. How do I deal with predicate name collisions? e.g. There’s another field user.settings.notifications which is an object, but there’s also user.notifications which is an array of notification objects.
    Without adding anything to my schema related to notifications, I can get query responses like
  "data": {
    "user": [
      {
        "uid": "0x5e81",
        "notifications": [
          {
            "to": "Bob"
          },
          {
            "to": "Michael"
          }
        ],
        "settings": {
          "notifications": [
            {
              "newsletterFrequency": "WEEKLY"
            }
          ]
        }
      }
    ]
  },

If I add notifications: uid . to my schema, I can get query responses like

  "data": {
    "user": [
      {
        "uid": "0x5e06",
        "settings": {
          "notifications": {
            "newsletterFrequency": "WEEKLY"
          }
        }
      }
    ]
  },

but I’ll get the error rpc error: code = Unknown desc = cannot add value with uid 5e8a to predicate notifications because one of the existing values does not match this uid, either delete the existing values first or modify the schema to 'notifications: [uid]' when I try to add to the user.notifications array. Is the only way to avoid this kind of error is to have universally unique predicates?

edit: seems like the question to my second question is I need to have universally unique predicates; I cannot have a notifications field of different types. https://docs.dgraph.io/master/query-language/#schema

For each predicate, the schema specifies the target’s type. If a predicate p has type T , then for all subject-predicate-object triples s p o the object o is of schema type T .

“user” is the query root and is returned as an array afaik. Usually, you can slice it [1:len-2] if you want it as an object and you know it is only one response.

Thanks for all your help!