github.com/weaviate/weaviate@v1.24.6/test/acceptance/graphql_resolvers/setup_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 package test 13 14 import ( 15 "context" 16 "fmt" 17 "math/rand" 18 "testing" 19 "time" 20 21 "github.com/go-openapi/strfmt" 22 "github.com/google/uuid" 23 "github.com/stretchr/testify/require" 24 "github.com/weaviate/weaviate/entities/models" 25 "github.com/weaviate/weaviate/entities/schema" 26 "github.com/weaviate/weaviate/entities/schema/crossref" 27 "github.com/weaviate/weaviate/test/docker" 28 "github.com/weaviate/weaviate/test/helper" 29 "github.com/weaviate/weaviate/test/helper/sample-schema/multishard" 30 ) 31 32 func TestGraphQL_AsyncIndexing(t *testing.T) { 33 ctx := context.Background() 34 compose, err := docker.New(). 35 WithWeaviate(). 36 WithText2VecContextionary(). 37 WithBackendFilesystem(). 38 WithWeaviateEnv("ASYNC_INDEXING", "true"). 39 Start(ctx) 40 require.NoError(t, err) 41 defer func() { 42 require.NoError(t, compose.Terminate(ctx)) 43 }() 44 45 defer helper.SetupClient(fmt.Sprintf("%s:%s", helper.ServerHost, helper.ServerPort)) 46 helper.SetupClient(compose.GetWeaviate().URI()) 47 48 testGraphQL(t) 49 } 50 51 func TestGraphQL_SyncIndexing(t *testing.T) { 52 testGraphQL(t) 53 } 54 55 func testGraphQL(t *testing.T) { 56 // tests with classes that have objects with same uuids 57 t.Run("import test data (near object search class)", addTestDataNearObjectSearch) 58 59 t.Run("running Get nearObject against shadowed objects", runningGetNearObjectWithShadowedObjects) 60 t.Run("running Aggregate nearObject against shadowed objects", runningAggregateNearObjectWithShadowedObjects) 61 t.Run("running Explore nearObject against shadowed objects", runningExploreNearObjectWithShadowedObjects) 62 63 deleteObjectClass(t, "NearObjectSearch") 64 deleteObjectClass(t, "NearObjectSearchShadow") 65 66 // setup tests 67 t.Run("setup test schema", addTestSchema) 68 t.Run("import test data (city, country, airport)", addTestDataCityAirport) 69 t.Run("import test data (companies)", addTestDataCompanies) 70 t.Run("import test data (person)", addTestDataPersons) 71 t.Run("import test data (pizzas)", addTestDataPizzas) 72 t.Run("import test data (array class)", addTestDataArrayClass) 73 t.Run("import test data (duplicates class)", addTestDataDuplicatesClass) 74 t.Run("import test data (500 random strings)", addTestDataRansomNotes) 75 t.Run("import test data (multi shard)", addTestDataMultiShard) 76 t.Run("import test data (date field class)", addDateFieldClass) 77 t.Run("import test data (custom vector class)", addTestDataCVC) 78 t.Run("import test data (class without properties)", addTestDataNoProperties) 79 t.Run("import test data (cursor api)", addTestDataCursorSearch) 80 81 // explore tests 82 t.Run("expected explore failures with invalid conditions", exploreWithExpectedFailures) 83 84 // get tests 85 t.Run("getting objects", gettingObjects) 86 t.Run("getting objects with filters", gettingObjectsWithFilters) 87 t.Run("getting objects with geo filters", gettingObjectsWithGeoFilters) 88 t.Run("getting objects with grouping", gettingObjectsWithGrouping) 89 t.Run("getting objects with additional props", gettingObjectsWithAdditionalProps) 90 t.Run("getting objects with near fields", gettingObjectsWithNearFields) 91 t.Run("getting objects with near fields with multi shard setup", gettingObjectsWithNearFieldsMultiShard) 92 t.Run("getting objects with sort", gettingObjectsWithSort) 93 t.Run("getting objects with hybrid search", getWithHybridSearch) 94 t.Run("expected get failures with invalid conditions", getsWithExpectedFailures) 95 t.Run("cursor through results", getWithCursorSearch) 96 t.Run("groupBy objects", groupByObjects) 97 98 // aggregate tests 99 t.Run("aggregates noPropsClass without grouping", aggregateNoPropsClassWithoutGroupByTest) 100 t.Run("aggregates arrayClass without grouping", aggregateArrayClassWithoutGroupByTest) 101 t.Run("aggregates arrayClass with grouping", aggregateArrayClassWithGroupByTest) 102 t.Run("aggregates duplicatesClass without grouping", aggregateDuplicatesClassWithoutGroupByTest) 103 t.Run("aggregates duplicatesClass with grouping", aggregateDuplicatesClassWithGroupByTest) 104 t.Run("aggregates city without grouping", aggregateCityClassWithoutGroupByTest) 105 t.Run("aggregates city with grouping", aggregateCityClassWithGroupByTest) 106 107 t.Run("aggregates local meta string props not set everywhere", localMeta_StringPropsNotSetEverywhere) 108 t.Run("aggregates local meta with where and nearText filters", localMetaWithWhereAndNearTextFilters) 109 t.Run("aggregates local meta with where and nearObject filters", localMetaWithWhereAndNearObjectFilters) 110 t.Run("aggregates local meta with nearVector filters", localMetaWithNearVectorFilter) 111 t.Run("aggregates local meta with where and nearVector nearMedia", localMetaWithWhereAndNearVectorFilters) 112 t.Run("aggregates local meta with where groupBy and nearMedia filters", localMetaWithWhereGroupByNearMediaFilters) 113 t.Run("aggregates local meta with objectLimit and nearMedia filters", localMetaWithObjectLimit) 114 t.Run("aggregates on date fields", aggregatesOnDateFields) 115 t.Run("aggregates with hybrid search", aggregationWithHybridSearch) 116 t.Run("expected aggregate failures with invalid conditions", aggregatesWithExpectedFailures) 117 118 t.Run("metrics count is stable when more classes are added", metricsCount) 119 120 // tear down 121 deleteObjectClass(t, "Person") 122 deleteObjectClass(t, "Pizza") 123 deleteObjectClass(t, "Country") 124 deleteObjectClass(t, "City") 125 deleteObjectClass(t, "Airport") 126 deleteObjectClass(t, "Company") 127 deleteObjectClass(t, "RansomNote") 128 deleteObjectClass(t, "MultiShard") 129 deleteObjectClass(t, "HasDateField") 130 deleteObjectClass(t, arrayClassName) 131 deleteObjectClass(t, duplicatesClassName) 132 deleteObjectClass(t, noPropsClassName) 133 deleteObjectClass(t, "CursorClass") 134 135 // only run after everything else is deleted, this way, we can also run an 136 // all-class Explore since all vectors which are now left have the same 137 // dimensions. 138 139 t.Run("getting objects with custom vectors", gettingObjectsWithCustomVectors) 140 t.Run("explore objects with custom vectors", exploreObjectsWithCustomVectors) 141 142 deleteObjectClass(t, "CustomVectorClass") 143 } 144 145 func addTestSchema(t *testing.T) { 146 createObjectClass(t, &models.Class{ 147 Class: "Country", 148 ModuleConfig: map[string]interface{}{ 149 "text2vec-contextionary": map[string]interface{}{ 150 "vectorizeClassName": true, 151 }, 152 }, 153 Properties: []*models.Property{ 154 { 155 Name: "name", 156 DataType: schema.DataTypeText.PropString(), 157 Tokenization: models.PropertyTokenizationWhitespace, 158 }, 159 }, 160 }) 161 162 // City class has only one vectorizable field: "name" 163 // the rest of the fields are explicitly set to skip vectorization 164 // to not to downgrade the distance/certainty result on which the 165 // aggregate tests are based on. 166 createObjectClass(t, &models.Class{ 167 Class: "City", 168 ModuleConfig: map[string]interface{}{ 169 "text2vec-contextionary": map[string]interface{}{ 170 "vectorizeClassName": true, 171 }, 172 }, 173 InvertedIndexConfig: &models.InvertedIndexConfig{IndexNullState: true, IndexPropertyLength: true, IndexTimestamps: true}, 174 Properties: []*models.Property{ 175 { 176 Name: "name", 177 DataType: schema.DataTypeText.PropString(), 178 Tokenization: models.PropertyTokenizationWhitespace, 179 ModuleConfig: map[string]interface{}{ 180 "text2vec-contextionary": map[string]interface{}{ 181 "skip": false, 182 }, 183 }, 184 }, 185 { 186 Name: "inCountry", 187 DataType: []string{"Country"}, 188 ModuleConfig: map[string]interface{}{ 189 "text2vec-contextionary": map[string]interface{}{ 190 "skip": true, 191 }, 192 }, 193 }, 194 { 195 Name: "population", 196 DataType: []string{"int"}, 197 ModuleConfig: map[string]interface{}{ 198 "text2vec-contextionary": map[string]interface{}{ 199 "skip": true, 200 }, 201 }, 202 }, 203 { 204 Name: "location", 205 DataType: []string{"geoCoordinates"}, 206 ModuleConfig: map[string]interface{}{ 207 "text2vec-contextionary": map[string]interface{}{ 208 "skip": true, 209 }, 210 }, 211 }, 212 { 213 Name: "isCapital", 214 DataType: []string{"boolean"}, 215 ModuleConfig: map[string]interface{}{ 216 "text2vec-contextionary": map[string]interface{}{ 217 "skip": true, 218 }, 219 }, 220 }, 221 { 222 Name: "cityArea", 223 DataType: []string{"number"}, 224 ModuleConfig: map[string]interface{}{ 225 "text2vec-contextionary": map[string]interface{}{ 226 "skip": true, 227 }, 228 }, 229 }, 230 { 231 Name: "cityRights", 232 DataType: []string{"date"}, 233 ModuleConfig: map[string]interface{}{ 234 "text2vec-contextionary": map[string]interface{}{ 235 "skip": true, 236 }, 237 }, 238 }, 239 { 240 Name: "timezones", 241 DataType: schema.DataTypeTextArray.PropString(), 242 Tokenization: models.PropertyTokenizationWhitespace, 243 ModuleConfig: map[string]interface{}{ 244 "text2vec-contextionary": map[string]interface{}{ 245 "skip": true, 246 }, 247 }, 248 }, 249 { 250 Name: "museums", 251 DataType: []string{"text[]"}, 252 ModuleConfig: map[string]interface{}{ 253 "text2vec-contextionary": map[string]interface{}{ 254 "skip": true, 255 }, 256 }, 257 }, 258 { 259 Name: "history", 260 DataType: []string{"text"}, 261 ModuleConfig: map[string]interface{}{ 262 "text2vec-contextionary": map[string]interface{}{ 263 "skip": true, 264 }, 265 }, 266 }, 267 { 268 Name: "phoneNumber", 269 DataType: []string{"phoneNumber"}, 270 ModuleConfig: map[string]interface{}{ 271 "text2vec-contextionary": map[string]interface{}{ 272 "skip": true, 273 }, 274 }, 275 }, 276 }, 277 }) 278 279 createObjectClass(t, &models.Class{ 280 Class: "Airport", 281 ModuleConfig: map[string]interface{}{ 282 "text2vec-contextionary": map[string]interface{}{ 283 "vectorizeClassName": true, 284 }, 285 }, 286 InvertedIndexConfig: &models.InvertedIndexConfig{ 287 CleanupIntervalSeconds: 60, 288 Stopwords: &models.StopwordConfig{ 289 Preset: "en", 290 }, 291 IndexTimestamps: true, 292 }, 293 Properties: []*models.Property{ 294 { 295 Name: "code", 296 DataType: schema.DataTypeText.PropString(), 297 Tokenization: models.PropertyTokenizationWhitespace, 298 }, 299 { 300 Name: "phone", 301 DataType: []string{"phoneNumber"}, 302 }, 303 { 304 Name: "inCity", 305 DataType: []string{"City"}, 306 }, 307 { 308 Name: "airportId", 309 DataType: []string{"uuid"}, 310 }, 311 }, 312 }) 313 314 createObjectClass(t, &models.Class{ 315 Class: "Company", 316 ModuleConfig: map[string]interface{}{ 317 "text2vec-contextionary": map[string]interface{}{ 318 "vectorizeClassName": false, 319 }, 320 }, 321 Properties: []*models.Property{ 322 { 323 Name: "name", 324 DataType: schema.DataTypeText.PropString(), 325 Tokenization: models.PropertyTokenizationWhitespace, 326 ModuleConfig: map[string]interface{}{ 327 "text2vec-contextionary": map[string]interface{}{ 328 "vectorizePropertyName": false, 329 }, 330 }, 331 }, 332 { 333 Name: "inCity", 334 DataType: []string{"City"}, 335 ModuleConfig: map[string]interface{}{ 336 "text2vec-contextionary": map[string]interface{}{ 337 "vectorizePropertyName": false, 338 }, 339 }, 340 }, 341 }, 342 }) 343 344 createObjectClass(t, &models.Class{ 345 Class: "Person", 346 ModuleConfig: map[string]interface{}{ 347 "text2vec-contextionary": map[string]interface{}{ 348 "vectorizeClassName": false, 349 }, 350 }, 351 Properties: []*models.Property{ 352 { 353 Name: "name", 354 DataType: schema.DataTypeText.PropString(), 355 Tokenization: models.PropertyTokenizationWhitespace, 356 ModuleConfig: map[string]interface{}{ 357 "text2vec-contextionary": map[string]interface{}{ 358 "vectorizePropertyName": false, 359 }, 360 }, 361 }, 362 { 363 Name: "livesIn", 364 DataType: []string{"City"}, 365 ModuleConfig: map[string]interface{}{ 366 "text2vec-contextionary": map[string]interface{}{ 367 "vectorizePropertyName": false, 368 }, 369 }, 370 }, 371 { 372 Name: "profession", 373 DataType: schema.DataTypeText.PropString(), 374 Tokenization: models.PropertyTokenizationField, 375 ModuleConfig: map[string]interface{}{ 376 "text2vec-contextionary": map[string]interface{}{ 377 "vectorizePropertyName": false, 378 }, 379 }, 380 }, 381 { 382 Name: "about", 383 DataType: schema.DataTypeTextArray.PropString(), 384 Tokenization: models.PropertyTokenizationField, 385 ModuleConfig: map[string]interface{}{ 386 "text2vec-contextionary": map[string]interface{}{ 387 "vectorizePropertyName": false, 388 }, 389 }, 390 }, 391 }, 392 }) 393 394 createObjectClass(t, &models.Class{ 395 Class: "Pizza", 396 ModuleConfig: map[string]interface{}{ 397 "text2vec-contextionary": map[string]interface{}{ 398 "vectorizeClassName": false, 399 }, 400 }, 401 Properties: []*models.Property{ 402 { 403 Name: "name", 404 DataType: schema.DataTypeText.PropString(), 405 Tokenization: models.PropertyTokenizationField, 406 ModuleConfig: map[string]interface{}{ 407 "text2vec-contextionary": map[string]interface{}{ 408 "vectorizePropertyName": false, 409 }, 410 }, 411 }, 412 { 413 Name: "description", 414 DataType: []string{string(schema.DataTypeText)}, 415 Tokenization: models.PropertyTokenizationWord, 416 ModuleConfig: map[string]interface{}{ 417 "text2vec-contextionary": map[string]interface{}{ 418 "vectorizePropertyName": false, 419 }, 420 }, 421 }, 422 }, 423 }) 424 425 createObjectClass(t, &models.Class{ 426 Class: "RansomNote", 427 ModuleConfig: map[string]interface{}{ 428 "text2vec-contextionary": map[string]interface{}{ 429 "vectorizeClassName": true, 430 }, 431 }, 432 Properties: []*models.Property{ 433 { 434 Name: "contents", 435 DataType: schema.DataTypeText.PropString(), 436 Tokenization: models.PropertyTokenizationWhitespace, 437 }, 438 }, 439 }) 440 441 createObjectClass(t, multishard.ClassContextionaryVectorizer()) 442 443 createObjectClass(t, &models.Class{ 444 Class: "HasDateField", 445 ModuleConfig: map[string]interface{}{ 446 "text2vec-contextionary": map[string]interface{}{ 447 "vectorizeClassName": true, 448 }, 449 }, 450 Properties: []*models.Property{ 451 { 452 Name: "unique", 453 DataType: schema.DataTypeText.PropString(), 454 Tokenization: models.PropertyTokenizationWhitespace, 455 }, 456 { 457 Name: "timestamp", 458 DataType: []string{"date"}, 459 }, 460 { 461 Name: "identical", 462 DataType: schema.DataTypeText.PropString(), 463 Tokenization: models.PropertyTokenizationWhitespace, 464 }, 465 }, 466 }) 467 468 createObjectClass(t, &models.Class{ 469 Class: "CustomVectorClass", 470 Vectorizer: "none", 471 Properties: []*models.Property{ 472 { 473 Name: "name", 474 DataType: schema.DataTypeText.PropString(), 475 Tokenization: models.PropertyTokenizationWhitespace, 476 }, 477 }, 478 }) 479 480 createObjectClass(t, noPropsClassSchema()) 481 createObjectClass(t, arrayClassSchema()) 482 createObjectClass(t, duplicatesClassSchema()) 483 } 484 485 const ( 486 netherlands strfmt.UUID = "67b79643-cf8b-4b22-b206-6e63dbb4e57a" 487 germany strfmt.UUID = "561eea29-b733-4079-b50b-cfabd78190b7" 488 amsterdam strfmt.UUID = "8f5f8e44-d348-459c-88b1-c1a44bb8f8be" 489 rotterdam strfmt.UUID = "660db307-a163-41d2-8182-560782cd018f" 490 berlin strfmt.UUID = "9b9cbea5-e87e-4cd0-89af-e2f424fd52d6" 491 dusseldorf strfmt.UUID = "6ffb03f8-a853-4ec5-a5d8-302e45aaaf13" 492 missingisland strfmt.UUID = "823abeca-eef3-41c7-b587-7a6977b08003" 493 nullisland strfmt.UUID = "823abeca-eef3-41c7-b587-7a6977b08067" 494 airport1 strfmt.UUID = "4770bb19-20fd-406e-ac64-9dac54c27a0f" 495 airport2 strfmt.UUID = "cad6ab9b-5bb9-4388-a933-a5bdfd23db37" 496 airport3 strfmt.UUID = "55a4dbbb-e2af-4b2a-901d-98146d1eeca7" 497 airport4 strfmt.UUID = "62d15920-b546-4844-bc87-3ae33268fab5" 498 cvc1 strfmt.UUID = "1ffeb3e1-1258-4c2a-afc3-55543f6c44b8" 499 cvc2 strfmt.UUID = "df22e5c4-5d17-49f9-a71d-f392a82bc086" 500 cvc3 strfmt.UUID = "c28a039a-d509-4c2e-940a-8b109e5bebf4" 501 502 quattroFormaggi strfmt.UUID = "152500c6-4a8a-4732-aede-9fcab7e43532" 503 fruttiDiMare strfmt.UUID = "a828e9aa-d1b6-4644-8569-30d404e31a0d" 504 hawaii strfmt.UUID = "ed75037b-0748-4970-811e-9fe835ed41d1" 505 doener strfmt.UUID = "a655292d-1b93-44a1-9a47-57b6922bb455" 506 ) 507 508 var ( 509 historyAmsterdam = "Due to its geographical location in what used to be wet peatland, the founding of Amsterdam is of a younger age than the founding of other urban centers in the Low Countries. However, in and around the area of what later became Amsterdam, local farmers settled as early as three millennia ago. They lived along the prehistoric IJ river and upstream of its tributary Amstel. The prehistoric IJ was a shallow and quiet stream in peatland behind beach ridges. This secluded area could grow there into an important local settlement center, especially in the late Bronze Age, the Iron Age and the Roman Age. Neolithic and Roman artefacts have also been found downstream of this area, in the prehistoric Amstel bedding under Amsterdam's Damrak and Rokin, such as shards of Bell Beaker culture pottery (2200-2000 BC) and a granite grinding stone (2700-2750 BC).[27][28] But the location of these artefacts around the river banks of the Amstel probably point to a presence of a modest semi-permanent or seasonal settlement of the previous mentioned local farmers. A permanent settlement would not have been possible, since the river mouth and the banks of the Amstel in this period in time were too wet for permanent habitation" 510 historyRotterdam = "On 7 July 1340, Count Willem IV of Holland granted city rights to Rotterdam, whose population then was only a few thousand.[14] Around the year 1350, a shipping canal (the Rotterdamse Schie) was completed, which provided Rotterdam access to the larger towns in the north, allowing it to become a local trans-shipment centre between the Netherlands, England and Germany, and to urbanize" 511 historyBerlin = "The earliest evidence of settlements in the area of today's Berlin are remnants of a house foundation dated to 1174, found in excavations in Berlin Mitte,[27] and a wooden beam dated from approximately 1192.[28] The first written records of towns in the area of present-day Berlin date from the late 12th century. Spandau is first mentioned in 1197 and Köpenick in 1209, although these areas did not join Berlin until 1920.[29] The central part of Berlin can be traced back to two towns. Cölln on the Fischerinsel is first mentioned in a 1237 document, and Berlin, across the Spree in what is now called the Nikolaiviertel, is referenced in a document from 1244.[28] 1237 is considered the founding date of the city.[30] The two towns over time formed close economic and social ties, and profited from the staple right on the two important trade routes Via Imperii and from Bruges to Novgorod.[12] In 1307, they formed an alliance with a common external policy, their internal administrations still being separated" 512 historyDusseldorf = "The first written mention of Düsseldorf (then called Dusseldorp in the local Low Rhenish dialect) dates back to 1135. Under Emperor Friedrich Barbarossa the small town of Kaiserswerth to the north of Düsseldorf became a well-fortified outpost, where soldiers kept a watchful eye on every movement on the Rhine. Kaiserswerth eventually became a suburb of Düsseldorf in 1929. In 1186, Düsseldorf came under the rule of the Counts of Berg. 14 August 1288 is one of the most important dates in the history of Düsseldorf. On this day the sovereign Count Adolf VIII of Berg granted the village on the banks of the Düssel town privileges. Before this, a bloody struggle for power had taken place between the Archbishop of Cologne and the count of Berg, culminating in the Battle of Worringen" 513 ) 514 515 func addTestDataCityAirport(t *testing.T) { 516 // countries 517 createObject(t, &models.Object{ 518 Class: "Country", 519 ID: netherlands, 520 Properties: map[string]interface{}{ 521 "name": "Netherlands", 522 }, 523 }) 524 createObject(t, &models.Object{ 525 Class: "Country", 526 ID: germany, 527 Properties: map[string]interface{}{ 528 "name": "Germany", 529 }, 530 }) 531 532 // cities 533 createObject(t, &models.Object{ 534 Class: "City", 535 ID: amsterdam, 536 Properties: map[string]interface{}{ 537 "name": "Amsterdam", 538 "population": 1800000, 539 "location": map[string]interface{}{ 540 "latitude": 52.366667, 541 "longitude": 4.9, 542 }, 543 "inCountry": []interface{}{ 544 map[string]interface{}{ 545 "beacon": crossref.NewLocalhost("Country", netherlands).String(), 546 }, 547 }, 548 "isCapital": true, 549 "cityArea": float64(891.95), 550 "cityRights": mustParseYear("1400"), 551 "timezones": []string{"CET", "CEST"}, 552 "museums": []string{"Stedelijk Museum", "Rijksmuseum"}, 553 "history": historyAmsterdam, 554 "phoneNumber": map[string]interface{}{ 555 "input": "+311000004", 556 }, 557 }, 558 }) 559 createObject(t, &models.Object{ 560 Class: "City", 561 ID: rotterdam, 562 Properties: map[string]interface{}{ 563 "name": "Rotterdam", 564 "population": 600000, 565 "inCountry": []interface{}{ 566 map[string]interface{}{ 567 "beacon": crossref.NewLocalhost("Country", netherlands).String(), 568 }, 569 }, 570 "isCapital": false, 571 "cityArea": float64(319.35), 572 "cityRights": mustParseYear("1283"), 573 "timezones": []string{"CET", "CEST"}, 574 "museums": []string{"Museum Boijmans Van Beuningen", "Wereldmuseum", "Witte de With Center for Contemporary Art"}, 575 "history": historyRotterdam, 576 "phoneNumber": map[string]interface{}{ 577 "input": "+311000000", 578 }, 579 }, 580 }) 581 createObject(t, &models.Object{ 582 Class: "City", 583 ID: berlin, 584 Properties: map[string]interface{}{ 585 "name": "Berlin", 586 "population": 3470000, 587 "inCountry": []interface{}{ 588 map[string]interface{}{ 589 "beacon": crossref.NewLocalhost("Country", germany).String(), 590 }, 591 }, 592 "isCapital": true, 593 "cityArea": float64(891.96), 594 "cityRights": mustParseYear("1400"), 595 "timezones": []string{"CET", "CEST"}, 596 "museums": []string{"German Historical Museum"}, 597 "history": historyBerlin, 598 "phoneNumber": map[string]interface{}{ 599 "input": "+311000002", 600 }, 601 }, 602 }) 603 createObject(t, &models.Object{ 604 Class: "City", 605 ID: dusseldorf, 606 Properties: map[string]interface{}{ 607 "name": "Dusseldorf", 608 "population": 600000, 609 "inCountry": []interface{}{ 610 map[string]interface{}{ 611 "beacon": crossref.NewLocalhost("Country", germany).String(), 612 }, 613 }, 614 "location": map[string]interface{}{ 615 "latitude": 51.225556, 616 "longitude": 6.782778, 617 }, 618 "isCapital": false, 619 "cityArea": float64(217.22), 620 "cityRights": mustParseYear("1135"), 621 "timezones": []string{"CET", "CEST"}, 622 "museums": []string{"Schlossturm", "Schiffahrt Museum", "Onomato"}, 623 "history": historyDusseldorf, 624 "phoneNumber": map[string]interface{}{ 625 "input": "+311000001", 626 }, 627 }, 628 }) 629 630 createObject(t, &models.Object{ 631 Class: "City", 632 ID: missingisland, 633 Properties: map[string]interface{}{ 634 "name": "Missing Island", 635 "population": 0, 636 "location": map[string]interface{}{ 637 "latitude": 0, 638 "longitude": 0, 639 }, 640 "isCapital": false, 641 }, 642 }) 643 644 createObject(t, &models.Object{ 645 Class: "City", 646 ID: nullisland, 647 Properties: map[string]interface{}{ 648 "name": nil, 649 "population": nil, 650 "inCountry": nil, 651 "location": nil, 652 "isCapital": nil, 653 "cityArea": nil, 654 "cityRights": nil, 655 "timezones": nil, 656 "museums": nil, 657 "history": nil, 658 "phoneNumber": nil, 659 }, 660 }) 661 662 // airports 663 createObject(t, &models.Object{ 664 Class: "Airport", 665 ID: airport1, 666 Properties: map[string]interface{}{ 667 "code": "10000", 668 "airportId": uuid.MustParse("00000000-0000-0000-0000-000000010000").String(), 669 "phone": map[string]interface{}{ 670 "input": "+311234567", 671 }, 672 "inCity": []interface{}{ 673 map[string]interface{}{ 674 "beacon": crossref.NewLocalhost("City", amsterdam).String(), 675 }, 676 }, 677 }, 678 }) 679 createObject(t, &models.Object{ 680 Class: "Airport", 681 ID: airport2, 682 Properties: map[string]interface{}{ 683 "code": "20000", 684 "airportId": uuid.MustParse("00000000-0000-0000-0000-000000020000").String(), 685 "inCity": []interface{}{ 686 map[string]interface{}{ 687 "beacon": crossref.NewLocalhost("City", rotterdam).String(), 688 }, 689 }, 690 }, 691 }) 692 createObject(t, &models.Object{ 693 Class: "Airport", 694 ID: airport3, 695 Properties: map[string]interface{}{ 696 "code": "30000", 697 "airportId": uuid.MustParse("00000000-0000-0000-0000-000000030000").String(), 698 "inCity": []interface{}{ 699 map[string]interface{}{ 700 "beacon": crossref.NewLocalhost("City", dusseldorf).String(), 701 }, 702 }, 703 }, 704 }) 705 createObject(t, &models.Object{ 706 Class: "Airport", 707 ID: airport4, 708 Properties: map[string]interface{}{ 709 "code": "40000", 710 "airportId": uuid.MustParse("00000000-0000-0000-0000-000000040000").String(), 711 "inCity": []interface{}{ 712 map[string]interface{}{ 713 "beacon": crossref.NewLocalhost("City", berlin).String(), 714 }, 715 }, 716 }, 717 }) 718 } 719 720 func addTestDataCompanies(t *testing.T) { 721 var ( 722 microsoft1 strfmt.UUID = "cfa3b21e-ca4f-4db7-a432-7fc6a23c534d" 723 microsoft2 strfmt.UUID = "8f75ed97-39dd-4294-bff7-ecabd7923062" 724 microsoft3 strfmt.UUID = "f343f51d-7e05-4084-bd66-d504db3b6bec" 725 apple1 strfmt.UUID = "477fec91-1292-4928-8f53-f0ff49c76900" 726 apple2 strfmt.UUID = "bb2cfdba-d4ba-4cf8-abda-e719ef35ac33" 727 apple3 strfmt.UUID = "b71d2b4c-3da1-4684-9c5e-aabd2a4f2998" 728 google1 strfmt.UUID = "8c2e21fc-46fe-4999-b41c-a800595129af" 729 google2 strfmt.UUID = "62b969c6-f184-4be0-8c40-7470af417cfc" 730 google3 strfmt.UUID = "c7829929-2037-4420-acbc-a433269feb93" 731 ) 732 733 type companyTemplate struct { 734 id strfmt.UUID 735 name string 736 inCity []strfmt.UUID 737 } 738 739 companies := []companyTemplate{ 740 {id: microsoft1, name: "Microsoft Inc.", inCity: []strfmt.UUID{dusseldorf}}, 741 {id: microsoft2, name: "Microsoft Incorporated", inCity: []strfmt.UUID{dusseldorf, amsterdam}}, 742 {id: microsoft3, name: "Microsoft", inCity: []strfmt.UUID{berlin}}, 743 {id: apple1, name: "Apple Inc."}, 744 {id: apple2, name: "Apple Incorporated"}, 745 {id: apple3, name: "Apple"}, 746 {id: google1, name: "Google Inc."}, 747 {id: google2, name: "Google Incorporated"}, 748 {id: google3, name: "Google"}, 749 } 750 751 // companies 752 for _, company := range companies { 753 inCity := []interface{}{} 754 for _, c := range company.inCity { 755 inCity = append(inCity, 756 map[string]interface{}{ 757 "beacon": crossref.NewLocalhost("City", c).String(), 758 }) 759 } 760 761 createObject(t, &models.Object{ 762 Class: "Company", 763 ID: company.id, 764 Properties: map[string]interface{}{ 765 "inCity": inCity, 766 "name": company.name, 767 }, 768 }) 769 } 770 771 assertGetObjectEventually(t, companies[len(companies)-1].id) 772 } 773 774 func addTestDataPersons(t *testing.T) { 775 var ( 776 alice strfmt.UUID = "5d0fa6ee-21c4-4b46-a735-f0208717837d" 777 bob strfmt.UUID = "8615585a-2960-482d-b19d-8bee98ade52c" 778 john strfmt.UUID = "3ef44474-b5e5-455d-91dc-d917b5b76165" 779 petra strfmt.UUID = "15d222c9-8c36-464b-bedb-113faa1c1e4c" 780 ) 781 782 type personTemplate struct { 783 id strfmt.UUID 784 name string 785 livesIn []strfmt.UUID 786 profession string 787 about []string 788 } 789 790 persons := []personTemplate{ 791 { 792 id: alice, name: "Alice", livesIn: []strfmt.UUID{}, profession: "Quality Control Analyst", 793 about: []string{"loves travelling very much"}, 794 }, 795 { 796 id: bob, name: "Bob", livesIn: []strfmt.UUID{amsterdam}, profession: "Mechanical Engineer", 797 about: []string{"loves travelling", "hates cooking"}, 798 }, 799 { 800 id: john, name: "John", livesIn: []strfmt.UUID{amsterdam, berlin}, profession: "Senior Mechanical Engineer", 801 about: []string{"hates swimming", "likes cooking", "loves travelling"}, 802 }, 803 { 804 id: petra, name: "Petra", livesIn: []strfmt.UUID{amsterdam, berlin, dusseldorf}, profession: "Quality Assurance Manager", 805 about: []string{"likes swimming", "likes cooking for family"}, 806 }, 807 } 808 809 // persons 810 for _, person := range persons { 811 livesIn := []interface{}{} 812 for _, c := range person.livesIn { 813 livesIn = append(livesIn, 814 map[string]interface{}{ 815 "beacon": crossref.NewLocalhost("City", c).String(), 816 }) 817 } 818 819 createObject(t, &models.Object{ 820 Class: "Person", 821 ID: person.id, 822 Properties: map[string]interface{}{ 823 "livesIn": livesIn, 824 "name": person.name, 825 "profession": person.profession, 826 "about": person.about, 827 }, 828 }) 829 } 830 831 assertGetObjectEventually(t, persons[len(persons)-1].id) 832 } 833 834 func addTestDataPizzas(t *testing.T) { 835 createObject(t, &models.Object{ 836 Class: "Pizza", 837 ID: quattroFormaggi, 838 Properties: map[string]interface{}{ 839 "name": "Quattro Formaggi", 840 "description": "Pizza quattro formaggi Italian: [ˈkwattro forˈmaddʒi] (four cheese pizza) is a variety of pizza in Italian cuisine that is topped with a combination of four kinds of cheese, usually melted together, with (rossa, red) or without (bianca, white) tomato sauce. It is popular worldwide, including in Italy,[1] and is one of the iconic items from pizzerias's menus.", 841 }, 842 }) 843 createObject(t, &models.Object{ 844 Class: "Pizza", 845 ID: fruttiDiMare, 846 Properties: map[string]interface{}{ 847 "name": "Frutti di Mare", 848 "description": "Frutti di Mare is an Italian type of pizza that may be served with scampi, mussels or squid. It typically lacks cheese, with the seafood being served atop a tomato sauce.", 849 }, 850 }) 851 createObject(t, &models.Object{ 852 Class: "Pizza", 853 ID: hawaii, 854 Properties: map[string]interface{}{ 855 "name": "Hawaii", 856 "description": "Universally accepted to be the best pizza ever created.", 857 }, 858 }) 859 createObject(t, &models.Object{ 860 Class: "Pizza", 861 ID: doener, 862 Properties: map[string]interface{}{ 863 "name": "Doener", 864 "description": "A innovation, some say revolution, in the pizza industry.", 865 }, 866 }) 867 868 assertGetObjectEventually(t, quattroFormaggi) 869 assertGetObjectEventually(t, fruttiDiMare) 870 assertGetObjectEventually(t, hawaii) 871 assertGetObjectEventually(t, doener) 872 } 873 874 func addTestDataCVC(t *testing.T) { 875 // add one object individually 876 createObject(t, &models.Object{ 877 Class: "CustomVectorClass", 878 ID: cvc1, 879 Vector: []float32{1.1, 1.1, 1.1}, 880 Properties: map[string]interface{}{ 881 "name": "Ford", 882 }, 883 }) 884 885 assertGetObjectEventually(t, cvc1) 886 887 createObjectsBatch(t, []*models.Object{ 888 { 889 Class: "CustomVectorClass", 890 ID: cvc2, 891 Vector: []float32{1.1, 1.1, 0.1}, 892 Properties: map[string]interface{}{ 893 "name": "Tesla", 894 }, 895 }, 896 { 897 Class: "CustomVectorClass", 898 ID: cvc3, 899 Vector: []float32{1.1, 0, 0}, 900 Properties: map[string]interface{}{ 901 "name": "Mercedes", 902 }, 903 }, 904 }) 905 assertGetObjectEventually(t, cvc3) 906 } 907 908 func addTestDataNoProperties(t *testing.T) { 909 for _, object := range noPropsClassObjects() { 910 createObject(t, object) 911 assertGetObjectEventually(t, object.ID) 912 } 913 } 914 915 func addTestDataArrayClass(t *testing.T) { 916 for _, object := range arrayClassObjects() { 917 createObject(t, object) 918 assertGetObjectEventually(t, object.ID) 919 } 920 } 921 922 func addTestDataDuplicatesClass(t *testing.T) { 923 for _, object := range duplicatesClassObjects() { 924 createObject(t, object) 925 assertGetObjectEventually(t, object.ID) 926 } 927 } 928 929 func addTestDataRansomNotes(t *testing.T) { 930 const ( 931 noteLengthMin = 4 932 noteLengthMax = 1024 933 934 batchSize = 10 935 numBatches = 50 936 ) 937 938 seededRand := rand.New(rand.NewSource(time.Now().UnixNano())) 939 940 for i := 0; i < numBatches; i++ { 941 batch := make([]*models.Object, batchSize) 942 for j := 0; j < batchSize; j++ { 943 noteLength := noteLengthMin + seededRand.Intn(noteLengthMax-noteLengthMin+1) 944 note := helper.GetRandomString(noteLength) 945 946 batch[j] = &models.Object{ 947 Class: "RansomNote", 948 Properties: map[string]interface{}{"contents": note}, 949 } 950 } 951 952 createObjectsBatch(t, batch) 953 } 954 } 955 956 func addTestDataMultiShard(t *testing.T) { 957 for _, multiShard := range multishard.Objects() { 958 helper.CreateObject(t, multiShard) 959 helper.AssertGetObjectEventually(t, multiShard.Class, multiShard.ID) 960 } 961 } 962 963 func addTestDataNearObjectSearch(t *testing.T) { 964 classNames := []string{"NearObjectSearch", "NearObjectSearchShadow"} 965 ids := []strfmt.UUID{ 966 "aa44bbee-ca5f-4db7-a412-5fc6a2300001", 967 "aa44bbee-ca5f-4db7-a412-5fc6a2300002", 968 "aa44bbee-ca5f-4db7-a412-5fc6a2300003", 969 "aa44bbee-ca5f-4db7-a412-5fc6a2300004", 970 "aa44bbee-ca5f-4db7-a412-5fc6a2300005", 971 } 972 names := []string{ 973 "Mount Everest", 974 "Amsterdam is a cool city", 975 "Football is a game where people run after ball", 976 "Berlin is Germany's capital city", 977 "London is a cool city", 978 } 979 980 for _, className := range classNames { 981 createObjectClass(t, &models.Class{ 982 Class: className, 983 ModuleConfig: map[string]interface{}{ 984 "text2vec-contextionary": map[string]interface{}{ 985 "vectorizeClassName": true, 986 }, 987 }, 988 Properties: []*models.Property{ 989 { 990 Name: "name", 991 DataType: schema.DataTypeText.PropString(), 992 Tokenization: models.PropertyTokenizationWhitespace, 993 }, 994 }, 995 }) 996 } 997 998 for i, id := range ids { 999 createObject(t, &models.Object{ 1000 Class: classNames[0], 1001 ID: id, 1002 Properties: map[string]interface{}{ 1003 "name": names[i], 1004 }, 1005 }) 1006 assertGetObjectEventually(t, id) 1007 createObject(t, &models.Object{ 1008 Class: classNames[1], 1009 ID: id, 1010 Properties: map[string]interface{}{ 1011 "name": fmt.Sprintf("altered contents of: %v", names[i]), 1012 }, 1013 }) 1014 assertGetObjectEventually(t, id) 1015 } 1016 1017 createObject(t, &models.Object{ 1018 Class: classNames[0], 1019 ID: "aa44bbee-ca5f-4db7-a412-5fc6a2300011", 1020 Properties: map[string]interface{}{ 1021 "name": "the same content goes here just for explore tests", 1022 }, 1023 }) 1024 assertGetObjectEventually(t, "aa44bbee-ca5f-4db7-a412-5fc6a2300011") 1025 createObject(t, &models.Object{ 1026 Class: classNames[1], 1027 ID: "aa44bbee-ca5f-4db7-a412-5fc6a2300011", 1028 Properties: map[string]interface{}{ 1029 "name": "the same content goes here just for explore tests", 1030 }, 1031 }) 1032 assertGetObjectEventually(t, "aa44bbee-ca5f-4db7-a412-5fc6a2300011") 1033 } 1034 1035 const ( 1036 cursorClassID1 = strfmt.UUID("00000000-0000-0000-0000-000000000001") 1037 cursorClassID2 = strfmt.UUID("00000000-0000-0000-0000-000000000002") 1038 cursorClassID3 = strfmt.UUID("00000000-0000-0000-0000-000000000003") 1039 cursorClassID4 = strfmt.UUID("00000000-0000-0000-0000-000000000004") 1040 cursorClassID5 = strfmt.UUID("00000000-0000-0000-0000-000000000005") 1041 cursorClassID6 = strfmt.UUID("00000000-0000-0000-0000-000000000006") 1042 cursorClassID7 = strfmt.UUID("00000000-0000-0000-0000-000000000007") 1043 ) 1044 1045 func addTestDataCursorSearch(t *testing.T) { 1046 className := "CursorClass" 1047 ids := []strfmt.UUID{ 1048 cursorClassID1, 1049 cursorClassID2, 1050 cursorClassID3, 1051 cursorClassID4, 1052 cursorClassID5, 1053 cursorClassID6, 1054 cursorClassID7, 1055 } 1056 names := []string{ 1057 "Mount Everest", 1058 "Amsterdam is a cool city", 1059 "Football is a game where people run after ball", 1060 "Berlin is Germany's capital city", 1061 "London is a cool city", 1062 "Wroclaw is a really cool city", 1063 "Brisbane is a city in Australia", 1064 } 1065 1066 createObjectClass(t, &models.Class{ 1067 Class: className, 1068 ModuleConfig: map[string]interface{}{ 1069 "text2vec-contextionary": map[string]interface{}{ 1070 "vectorizeClassName": true, 1071 }, 1072 }, 1073 Properties: []*models.Property{ 1074 { 1075 Name: "name", 1076 DataType: schema.DataTypeText.PropString(), 1077 Tokenization: models.PropertyTokenizationWhitespace, 1078 }, 1079 }, 1080 }) 1081 1082 for i, id := range ids { 1083 createObject(t, &models.Object{ 1084 Class: className, 1085 ID: id, 1086 Properties: map[string]interface{}{ 1087 "name": names[i], 1088 }, 1089 }) 1090 assertGetObjectEventually(t, id) 1091 } 1092 } 1093 1094 func addDateFieldClass(t *testing.T) { 1095 timestamps := []string{ 1096 "2022-06-16T22:18:59.640162Z", 1097 "2022-06-16T22:19:01.495967Z", 1098 "2022-06-16T22:19:03.495596Z", 1099 "2022-06-16T22:19:04.3828349Z", 1100 "2022-06-16T22:19:05.894857Z", 1101 "2022-06-16T22:19:06.394958Z", 1102 "2022-06-16T22:19:07.589828Z", 1103 "2022-06-16T22:19:08.112395Z", 1104 "2022-06-16T22:19:10.339493Z", 1105 "2022-06-16T22:19:11.837473Z", 1106 } 1107 1108 for i := 0; i < len(timestamps); i++ { 1109 createObject(t, &models.Object{ 1110 Class: "HasDateField", 1111 Properties: map[string]interface{}{ 1112 "unique": fmt.Sprintf("#%d", i+1), 1113 "timestamp": timestamps[i], 1114 "identical": "hello!", 1115 }, 1116 }) 1117 } 1118 } 1119 1120 func mustParseYear(year string) time.Time { 1121 date := fmt.Sprintf("%s-01-01T00:00:00+02:00", year) 1122 asTime, err := time.Parse(time.RFC3339, date) 1123 if err != nil { 1124 panic(err) 1125 } 1126 return asTime 1127 }