String array out of order

Very new user of Dgraph here but so far, loving it!

I’ve encountered a really strange bug(?) it seems

In my schema I have: Product.facts [string]

  const createProduct = new Mutation();
  const x = {
    "dgraph.type": "Product",
    "Product.attributes": "{\"string\":\"42\",\"number\":42,\"nested\":{\"nested\":\"property\"},\"boolean\":false}",
    "Product.brand": {
      "uid": "0x24f"
    },
    "Product.facts": [
      "test fact #1",
      "test fact #2",
      "test fact #3"
    ],
    "Product.media": [],
    "Product.name": "test product name",
    "Product.subtitle": "test product subtitle",
    "Product.description": "test product description",
    "uid": "_:product"
  }
  createProduct.setSetJson(x);
  createProduct.setCommitNow(true);

  const clientStub = new DgraphClientStub(<dgraph-url>, grpc.credentials.createInsecure());
const client = new DgraphClient(clientStub);
client.setDebugMode(true)
  const productId = await client.newTxn()
    .mutate(createProduct)
    .then(r => r.getUidsMap().get('product'))

Then I go to Ratel and check the inserted object, and I see:

{
  node(func: uid(<product ID>)) {
    Product.facts
  }
}

And I see:

        "Product.facts": [
          "test fact #2",
          "test fact #1",
          "test fact #3"
        ]

Why are strings out of order?

The list type in Dgraph behaves like an unordered set (i.e. does not guarantee order).

Primitive lists do not permit sorting. Instead, we can create separate nodes for each fact:

{
  set {
    _:f1 <description> "test fact #1" .
    _:f2 <description> "test fact #2" .
    _:f3 <description> "test fact #3" .
    _:p1 <has_fact> _:f1 .
    _:p1 <has_fact> _:f2 .
    _:p1 <has_fact> _:f3 .
  }
}

Now, we can easily sort the output:

{
  node(func: uid(0x6)) {
    has_fact(orderasc: description) {
      description
    }
  }
}
2 Likes

I see. Thanks!

FYI, I solved this for my use case by storing an ordered array as JSON in a string.

This may not fit your use case though. For my use case, 1) I will be updating the entire array at once and not item by item; 2) I will not need to search for the items in the array, although search indexing would work on the string such as anyofterms or alloftext depending on your applied indexing. 3) I will always need to entire list at once, I never need just a single item from the list.

1 Like