Why index collection shows null not data documents

Hi
I’m facing an unwanted behavior that when I create an index with values it returns null instead of data object. Check screenshot:

How I make index:
Via UI

Via SHELL:

CreateIndex({
  name: "by_ref_location",
  source: Collection("allValues"),
  values: [{ field: ["ref"] }, { field: ["data", "location"] }],
})

But I am sure that documents have location object:

"location": {
      "latitude": "51.5145898586422",
      "longitude": "-0.0562515236706747",
      "postcode": {
        "name": "E1 2HU",
        "latitude": 51.514538,
        "longitude": -0.055845
      }
    }

I even tried only getting data but it’s still returning null:

CreateIndex({
  name: "by_ref_location",
  source: Collection("allValues"),
  values: [{ field: ["ref"] }, { field: ["data"] }],
})

Fauna does not save object types in Indexes. If the path defined in terms or values is an object, it resolves to null.

Our docs state this about terms. The same rule applies to Index values, so we need to update that:

Terms [and values] must refer to fields containing scalar Values. When a term [or value] points to a document field or index binding result that contains an array, one index entry per array item is created. Objects are not indexed.

Consider that Index values define how an Index is to be sorted. How can an index get sorted by an object? It can’t, so while building the index an object is interpreted as a null value.

Alternatives

Index many values

You can add each value to the Index

CreateIndex({
  name: "all_values",
  source: Collection("allValues"),
  values: [
    { field: ["ref"] }, 
    { field: ["data", "location", "latitude"] },
    { field: ["data", "location", "longitude"] },
    { field: ["data", "location", "postcode", "name"] },
    // ...
  ],
})

Index bindings

If there is a way to transform the object into a single value, then you can use a binding. For some objects, there is a clear string representation that could be used. For your location field, maybe computing some kind of geohash number would be helpful.

CreateIndex({
  name: "all_values",
  source: {
    collection: Collection("allValues"),
    fields: {
      location: Query(Lambda("doc",
        // Some computation
      ))
    }
  },
  values: [
    { field: ["ref"] }, 
    { binding: "location" },
  ],
})

Other Notes

Searching ranges of values

I see your Index called by_ref_location. Even if you had an efficient binding or added all the location details to values, this would not be very good to search by, if searching by location is what you want to do.

The reason is that providing Index values sorts the Index by those values, and you can later use Range to execute a search over the values. However, if you list ref as the first value, then the Index entries will be sorted by ID and the location data will never have any value.

If you wish to search by a range of values, make sure they appear first in the values list

CreateIndex({
  name: "value__latitude_asc_longitude_asc",
  source: Collection("allValues"),
  values: [
    { field: ["data", "location", "latitude"] },
    { field: ["data", "location", "longitude"] },
    // ...
    { field: ["ref"] },  // ref last
  ],
})
Paginate(
  Range(
    Match(Index('value__latitude_asc_longitude_asc')),
    ["23452", "56353"],
    ["23452", "56500"],
  )
)

Geohashes

Geohashes are not a native datatype in Fauna, but it is possible to work with them in Fauna. Here is a feature request and discussion that you might find interesting

I’ve created an internal issue to update our documentation.

I went with first example for now. I don’t need search for now!

Thank you :blush:

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.