diff --git a/systest/queries_test.go b/systest/queries_test.go index 715f7971c12..dc6d42a2262 100644 --- a/systest/queries_test.go +++ b/systest/queries_test.go @@ -53,6 +53,7 @@ func TestQuery(t *testing.T) { t.Run("hash index queries", wrap(QueryHashIndex)) t.Run("fuzzy matching", wrap(FuzzyMatch)) t.Run("regexp with toggled trigram index", wrap(RegexpToggleTrigramIndex)) + t.Run("eq with altering order of trigram and term index", wrap(EqWithAlteredIndexOrder)) t.Run("groupby uid that works", wrap(GroupByUidWorks)) t.Run("parameterized cascade", wrap(CascadeParams)) t.Run("cleanup", wrap(SchemaQueryCleanup)) @@ -1346,6 +1347,41 @@ func RegexpToggleTrigramIndex(t *testing.T, c *dgo.Dgraph) { require.Contains(t, err.Error(), "Attribute name does not have trigram index for regex matching.") } +func EqWithAlteredIndexOrder(t *testing.T, c *dgo.Dgraph) { + ctx := context.Background() + + // first, let's set the schema with term before trigram + op := &api.Operation{Schema: `name: string @index(term, trigram) .`} + require.NoError(t, c.Alter(ctx, op)) + + // fill up some data + txn := c.NewTxn() + _, err := txn.Mutate(ctx, &api.Mutation{ + SetNquads: []byte(` + _:x1 "Alice" . + _:x2 "Bob" . + `), + }) + require.NoError(t, err) + require.NoError(t, txn.Commit(ctx)) + + // querying with eq should work + q := `{q(func: eq(name, "Alice")) {name}}` + expectedResult := `{"q":[{"name":"Alice"}]}` + resp, err := c.NewReadOnlyTxn().Query(ctx, q) + require.NoError(t, err) + testutil.CompareJSON(t, expectedResult, string(resp.Json)) + + // now, let's set the schema with trigram before term + op = &api.Operation{Schema: `name: string @index(trigram, term) .`} + require.NoError(t, c.Alter(ctx, op)) + + // querying with eq should still work + resp, err = c.NewReadOnlyTxn().Query(ctx, q) + require.NoError(t, err) + testutil.CompareJSON(t, expectedResult, string(resp.Json)) +} + func GroupByUidWorks(t *testing.T, c *dgo.Dgraph) { ctx := context.Background() diff --git a/wiki/content/query-language/functions.md b/wiki/content/query-language/functions.md index 451a11d943e..ee60056e9d7 100644 --- a/wiki/content/query-language/functions.md +++ b/wiki/content/query-language/functions.md @@ -265,7 +265,7 @@ Index Required: An index is required for the `eq(predicate, ...)` forms (see tab | `int` | `int` | | `float` | `float` | | `bool` | `bool` | -| `string` | `exact`, `hash` | +| `string` | `exact`, `hash`, `term`, `fulltext` | | `dateTime` | `dateTime` | Test for equality of a predicate or variable to a value or find in a list of values. diff --git a/worker/tokens.go b/worker/tokens.go index 3d4e97c5068..f7e6e04130d 100644 --- a/worker/tokens.go +++ b/worker/tokens.go @@ -85,7 +85,7 @@ func pickTokenizer(ctx context.Context, attr string, f string) (tok.Tokenizer, e tokenizers := schema.State().Tokenizer(ctx, attr) for _, t := range tokenizers { - // If function is eq and we found a tokenizer thats !Lossy(), lets return it + // If function is eq and we found a tokenizer that's !Lossy(), lets return it switch f { case "eq": // For equality, find a non-lossy tokenizer. @@ -105,7 +105,17 @@ func pickTokenizer(ctx context.Context, attr string, f string) (tok.Tokenizer, e return nil, errors.Errorf("Attribute:%s does not have proper index for comparison", attr) } - // We didn't find a sortable or !isLossy() tokenizer, lets return the first one. + // If we didn't find a !isLossy() tokenizer for eq function on string type predicates, + // then let's see if we can find a non-trigram tokenizer + if typ, err := schema.State().TypeOf(attr); err == nil && typ == types.StringID { + for _, t := range tokenizers { + if t.Identifier() != tok.IdentTrigram { + return t, nil + } + } + } + + // otherwise, lets return the first one. return tokenizers[0], nil }