github.com/weaviate/weaviate@v1.24.6/adapters/repos/db/crud_noindex_property_integration_test.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 //go:build integrationTest 13 // +build integrationTest 14 15 package db 16 17 import ( 18 "context" 19 "testing" 20 21 "github.com/go-openapi/strfmt" 22 "github.com/sirupsen/logrus/hooks/test" 23 "github.com/stretchr/testify/assert" 24 "github.com/stretchr/testify/require" 25 "github.com/weaviate/weaviate/entities/additional" 26 "github.com/weaviate/weaviate/entities/dto" 27 "github.com/weaviate/weaviate/entities/filters" 28 "github.com/weaviate/weaviate/entities/models" 29 "github.com/weaviate/weaviate/entities/schema" 30 "github.com/weaviate/weaviate/entities/search" 31 enthnsw "github.com/weaviate/weaviate/entities/vectorindex/hnsw" 32 ) 33 34 func TestCRUD_NoIndexProp(t *testing.T) { 35 dirName := t.TempDir() 36 37 vFalse := false 38 logger, _ := test.NewNullLogger() 39 thingclass := &models.Class{ 40 Class: "ThingClassWithNoIndexProps", 41 VectorIndexConfig: enthnsw.NewDefaultUserConfig(), 42 InvertedIndexConfig: invertedConfig(), 43 Properties: []*models.Property{{ 44 Name: "stringProp", 45 DataType: schema.DataTypeText.PropString(), 46 Tokenization: models.PropertyTokenizationWhitespace, 47 }, { 48 Name: "hiddenStringProp", 49 DataType: schema.DataTypeText.PropString(), 50 Tokenization: models.PropertyTokenizationWhitespace, 51 IndexFilterable: &vFalse, 52 IndexSearchable: &vFalse, 53 }}, 54 } 55 schemaGetter := &fakeSchemaGetter{ 56 schema: schema.Schema{Objects: &models.Schema{Classes: nil}}, 57 shardState: singleShardState(), 58 } 59 repo, err := New(logger, Config{ 60 RootPath: dirName, 61 QueryMaximumResults: 10000, 62 MaxImportGoroutinesFactor: 1, 63 MemtablesFlushDirtyAfter: 60, 64 }, &fakeRemoteClient{}, &fakeNodeResolver{}, &fakeRemoteNodeClient{}, &fakeReplicationClient{}, nil) 65 require.Nil(t, err) 66 repo.SetSchemaGetter(schemaGetter) 67 require.Nil(t, repo.WaitForStartup(testCtx())) 68 defer repo.Shutdown(context.Background()) 69 70 migrator := NewMigrator(repo, logger) 71 72 t.Run("creating the thing class", func(t *testing.T) { 73 require.Nil(t, 74 migrator.AddClass(context.Background(), thingclass, schemaGetter.shardState)) 75 76 // update schema getter so it's in sync with class 77 schemaGetter.schema = schema.Schema{ 78 Objects: &models.Schema{ 79 Classes: []*models.Class{thingclass}, 80 }, 81 } 82 }) 83 84 thingID := strfmt.UUID("9f119c4f-80da-4ae5-bfd1-e4b63054125f") 85 86 t.Run("adding a thing", func(t *testing.T) { 87 thing := &models.Object{ 88 CreationTimeUnix: 1565612833955, 89 LastUpdateTimeUnix: 1000001, 90 ID: thingID, 91 Class: "ThingClassWithNoIndexProps", 92 Properties: map[string]interface{}{ 93 "stringProp": "some value", 94 "hiddenStringProp": "some hidden value", 95 }, 96 } 97 vector := []float32{1, 3, 5, 0.4} 98 err := repo.PutObject(context.Background(), thing, vector, nil, nil) 99 100 assert.Nil(t, err) 101 }) 102 103 t.Run("all props are present when getting by id", func(t *testing.T) { 104 res, err := repo.ObjectByID(context.Background(), thingID, search.SelectProperties{}, additional.Properties{}, "") 105 expectedSchema := map[string]interface{}{ 106 "stringProp": "some value", 107 "hiddenStringProp": "some hidden value", 108 "id": thingID, 109 } 110 111 require.Nil(t, err) 112 assert.Equal(t, expectedSchema, res.Schema) 113 }) 114 115 // Same as above, but with Object() 116 t.Run("all props are present when getting by id and class", func(t *testing.T) { 117 res, err := repo.Object(context.Background(), "ThingClassWithNoIndexProps", thingID, 118 search.SelectProperties{}, additional.Properties{}, nil, "") 119 expectedSchema := map[string]interface{}{ 120 "stringProp": "some value", 121 "hiddenStringProp": "some hidden value", 122 "id": thingID, 123 } 124 125 require.Nil(t, err) 126 assert.Equal(t, expectedSchema, res.Schema) 127 }) 128 129 t.Run("class search on the noindex prop errors", func(t *testing.T) { 130 _, err := repo.Search(context.Background(), dto.GetParams{ 131 ClassName: "ThingClassWithNoIndexProps", 132 Pagination: &filters.Pagination{ 133 Limit: 10, 134 }, 135 Filters: buildFilter("hiddenStringProp", "hidden", eq, schema.DataTypeText), 136 }) 137 138 require.NotNil(t, err) 139 assert.Contains(t, err.Error(), "Filtering by property 'hiddenStringProp' requires inverted index. "+ 140 "Is `indexFilterable` option of property 'hiddenStringProp' enabled? "+ 141 "Set it to `true` or leave empty") 142 }) 143 144 t.Run("class search on timestamp prop with no timestamp indexing error", func(t *testing.T) { 145 _, err := repo.Search(context.Background(), dto.GetParams{ 146 ClassName: "ThingClassWithNoIndexProps", 147 Pagination: &filters.Pagination{ 148 Limit: 10, 149 }, 150 Filters: buildFilter("_creationTimeUnix", "1234567891011", eq, schema.DataTypeText), 151 }) 152 153 require.NotNil(t, err) 154 assert.Contains(t, err.Error(), 155 "Timestamps must be indexed to be filterable! Add `IndexTimestamps: true` to the InvertedIndexConfig in") 156 }) 157 }