github.com/weaviate/weaviate@v1.24.6/test/acceptance/graphql_resolvers/local_aggregate_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 "encoding/json" 16 "fmt" 17 "strconv" 18 "testing" 19 20 "github.com/stretchr/testify/assert" 21 "github.com/stretchr/testify/require" 22 "github.com/weaviate/weaviate/entities/schema" 23 "github.com/weaviate/weaviate/test/helper" 24 graphqlhelper "github.com/weaviate/weaviate/test/helper/graphql" 25 ) 26 27 // This test prevents a regression on the fix for 28 // https://github.com/weaviate/weaviate/issues/824 29 func localMeta_StringPropsNotSetEverywhere(t *testing.T) { 30 graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 31 { 32 Aggregate { 33 City { 34 name { 35 topOccurrences { 36 occurs 37 value 38 } 39 } 40 } 41 } 42 } 43 `) 44 } 45 46 func localMetaWithWhereAndNearTextFilters(t *testing.T) { 47 t.Run("with distance", func(t *testing.T) { 48 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 49 { 50 Aggregate{ 51 City (where: { 52 valueBoolean: true, 53 operator: Equal, 54 path: ["isCapital"] 55 } 56 nearText: { 57 concepts: ["Amsterdam"] 58 distance: 0.2 59 } 60 ){ 61 meta { 62 count 63 } 64 isCapital { 65 count 66 percentageFalse 67 percentageTrue 68 totalFalse 69 totalTrue 70 type 71 } 72 population { 73 mean 74 count 75 maximum 76 minimum 77 sum 78 type 79 } 80 inCountry { 81 pointingTo 82 type 83 } 84 name { 85 topOccurrences { 86 occurs 87 value 88 } 89 type 90 count 91 } 92 } 93 } 94 } 95 `) 96 97 t.Run("meta count", func(t *testing.T) { 98 meta := result.Get("Aggregate", "City").AsSlice()[0].(map[string]interface{})["meta"] 99 count := meta.(map[string]interface{})["count"] 100 expected := json.Number("1") 101 assert.Equal(t, expected, count) 102 }) 103 104 t.Run("boolean props", func(t *testing.T) { 105 isCapital := result.Get("Aggregate", "City").AsSlice()[0].(map[string]interface{})["isCapital"] 106 expected := map[string]interface{}{ 107 "count": json.Number("1"), 108 "percentageTrue": json.Number("1"), 109 "percentageFalse": json.Number("0"), 110 "totalTrue": json.Number("1"), 111 "totalFalse": json.Number("0"), 112 "type": "boolean", 113 } 114 assert.Equal(t, expected, isCapital) 115 }) 116 117 t.Run("int/number props", func(t *testing.T) { 118 population := result.Get("Aggregate", "City").AsSlice()[0].(map[string]interface{})["population"] 119 expected := map[string]interface{}{ 120 "mean": json.Number("1800000"), 121 "count": json.Number("1"), 122 "maximum": json.Number("1800000"), 123 "minimum": json.Number("1800000"), 124 "sum": json.Number("1800000"), 125 "type": "int", 126 } 127 assert.Equal(t, expected, population) 128 }) 129 130 t.Run("ref prop", func(t *testing.T) { 131 inCountry := result.Get("Aggregate", "City").AsSlice()[0].(map[string]interface{})["inCountry"] 132 expected := map[string]interface{}{ 133 "pointingTo": []interface{}{"Country"}, 134 "type": "cref", 135 } 136 assert.Equal(t, expected, inCountry) 137 }) 138 139 t.Run("string prop", func(t *testing.T) { 140 name := result.Get("Aggregate", "City"). 141 AsSlice()[0].(map[string]interface{})["name"].(map[string]interface{}) 142 typeField := name["type"] 143 topOccurrences := name["topOccurrences"] 144 145 assert.Equal(t, schema.DataTypeText.String(), typeField) 146 147 expectedTopOccurrences := []interface{}{ 148 map[string]interface{}{ 149 "value": "Amsterdam", 150 "occurs": json.Number("1"), 151 }, 152 } 153 assert.ElementsMatch(t, expectedTopOccurrences, topOccurrences) 154 }) 155 }) 156 157 t.Run("with certainty", func(t *testing.T) { 158 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 159 { 160 Aggregate{ 161 City (where: { 162 valueBoolean: true, 163 operator: Equal, 164 path: ["isCapital"] 165 } 166 nearText: { 167 concepts: ["Amsterdam"] 168 certainty: 0.9 169 } 170 ){ 171 meta { 172 count 173 } 174 isCapital { 175 count 176 percentageFalse 177 percentageTrue 178 totalFalse 179 totalTrue 180 type 181 } 182 population { 183 mean 184 count 185 maximum 186 minimum 187 sum 188 type 189 } 190 inCountry { 191 pointingTo 192 type 193 } 194 name { 195 topOccurrences { 196 occurs 197 value 198 } 199 type 200 count 201 } 202 } 203 } 204 }`) 205 206 t.Run("meta count", func(t *testing.T) { 207 meta := result.Get("Aggregate", "City").AsSlice()[0].(map[string]interface{})["meta"] 208 count := meta.(map[string]interface{})["count"] 209 expected := json.Number("1") 210 assert.Equal(t, expected, count) 211 }) 212 213 t.Run("boolean props", func(t *testing.T) { 214 isCapital := result.Get("Aggregate", "City").AsSlice()[0].(map[string]interface{})["isCapital"] 215 expected := map[string]interface{}{ 216 "count": json.Number("1"), 217 "percentageTrue": json.Number("1"), 218 "percentageFalse": json.Number("0"), 219 "totalTrue": json.Number("1"), 220 "totalFalse": json.Number("0"), 221 "type": "boolean", 222 } 223 assert.Equal(t, expected, isCapital) 224 }) 225 226 t.Run("int/number props", func(t *testing.T) { 227 population := result.Get("Aggregate", "City").AsSlice()[0].(map[string]interface{})["population"] 228 expected := map[string]interface{}{ 229 "mean": json.Number("1800000"), 230 "count": json.Number("1"), 231 "maximum": json.Number("1800000"), 232 "minimum": json.Number("1800000"), 233 "sum": json.Number("1800000"), 234 "type": "int", 235 } 236 assert.Equal(t, expected, population) 237 }) 238 239 t.Run("ref prop", func(t *testing.T) { 240 inCountry := result.Get("Aggregate", "City").AsSlice()[0].(map[string]interface{})["inCountry"] 241 expected := map[string]interface{}{ 242 "pointingTo": []interface{}{"Country"}, 243 "type": "cref", 244 } 245 assert.Equal(t, expected, inCountry) 246 }) 247 248 t.Run("string prop", func(t *testing.T) { 249 name := result.Get("Aggregate", "City"). 250 AsSlice()[0].(map[string]interface{})["name"].(map[string]interface{}) 251 typeField := name["type"] 252 topOccurrences := name["topOccurrences"] 253 254 assert.Equal(t, schema.DataTypeText.String(), typeField) 255 256 expectedTopOccurrences := []interface{}{ 257 map[string]interface{}{ 258 "value": "Amsterdam", 259 "occurs": json.Number("1"), 260 }, 261 } 262 assert.ElementsMatch(t, expectedTopOccurrences, topOccurrences) 263 }) 264 }) 265 } 266 267 func localMetaWithWhereAndNearObjectFilters(t *testing.T) { 268 t.Run("with distance", func(t *testing.T) { 269 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 270 { 271 Aggregate{ 272 City (where: { 273 valueBoolean: true, 274 operator: Equal, 275 path: ["isCapital"] 276 } 277 nearObject: { 278 id: "9b9cbea5-e87e-4cd0-89af-e2f424fd52d6" 279 distance: 0.2 280 } 281 ){ 282 meta { 283 count 284 } 285 isCapital { 286 count 287 percentageFalse 288 percentageTrue 289 totalFalse 290 totalTrue 291 type 292 } 293 population { 294 mean 295 count 296 maximum 297 minimum 298 sum 299 type 300 } 301 inCountry { 302 pointingTo 303 type 304 } 305 name { 306 topOccurrences { 307 occurs 308 value 309 } 310 type 311 count 312 } 313 } 314 } 315 }`) 316 317 t.Run("meta count", func(t *testing.T) { 318 meta := result.Get("Aggregate", "City").AsSlice()[0].(map[string]interface{})["meta"] 319 count := meta.(map[string]interface{})["count"] 320 expected := json.Number("1") 321 assert.Equal(t, expected, count) 322 }) 323 324 t.Run("boolean props", func(t *testing.T) { 325 isCapital := result.Get("Aggregate", "City").AsSlice()[0].(map[string]interface{})["isCapital"] 326 expected := map[string]interface{}{ 327 "count": json.Number("1"), 328 "percentageTrue": json.Number("1"), 329 "percentageFalse": json.Number("0"), 330 "totalTrue": json.Number("1"), 331 "totalFalse": json.Number("0"), 332 "type": "boolean", 333 } 334 assert.Equal(t, expected, isCapital) 335 }) 336 337 t.Run("int/number props", func(t *testing.T) { 338 population := result.Get("Aggregate", "City").AsSlice()[0].(map[string]interface{})["population"] 339 expected := map[string]interface{}{ 340 "mean": json.Number("3470000"), 341 "count": json.Number("1"), 342 "maximum": json.Number("3470000"), 343 "minimum": json.Number("3470000"), 344 "sum": json.Number("3470000"), 345 "type": "int", 346 } 347 assert.Equal(t, expected, population) 348 }) 349 350 t.Run("ref prop", func(t *testing.T) { 351 inCountry := result.Get("Aggregate", "City").AsSlice()[0].(map[string]interface{})["inCountry"] 352 expected := map[string]interface{}{ 353 "pointingTo": []interface{}{"Country"}, 354 "type": "cref", 355 } 356 assert.Equal(t, expected, inCountry) 357 }) 358 359 t.Run("string prop", func(t *testing.T) { 360 name := result.Get("Aggregate", "City"). 361 AsSlice()[0].(map[string]interface{})["name"].(map[string]interface{}) 362 typeField := name["type"] 363 topOccurrences := name["topOccurrences"] 364 365 assert.Equal(t, schema.DataTypeText.String(), typeField) 366 367 expectedTopOccurrences := []interface{}{ 368 map[string]interface{}{ 369 "value": "Berlin", 370 "occurs": json.Number("1"), 371 }, 372 } 373 assert.ElementsMatch(t, expectedTopOccurrences, topOccurrences) 374 }) 375 }) 376 377 t.Run("with certainty", func(t *testing.T) { 378 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 379 { 380 Aggregate{ 381 City (where: { 382 valueBoolean: true, 383 operator: Equal, 384 path: ["isCapital"] 385 } 386 nearObject: { 387 id: "9b9cbea5-e87e-4cd0-89af-e2f424fd52d6" 388 certainty: 0.9 389 } 390 ){ 391 meta { 392 count 393 } 394 isCapital { 395 count 396 percentageFalse 397 percentageTrue 398 totalFalse 399 totalTrue 400 type 401 } 402 population { 403 mean 404 count 405 maximum 406 minimum 407 sum 408 type 409 } 410 inCountry { 411 pointingTo 412 type 413 } 414 name { 415 topOccurrences { 416 occurs 417 value 418 } 419 type 420 count 421 } 422 } 423 } 424 }`) 425 426 t.Run("meta count", func(t *testing.T) { 427 meta := result.Get("Aggregate", "City").AsSlice()[0].(map[string]interface{})["meta"] 428 count := meta.(map[string]interface{})["count"] 429 expected := json.Number("1") 430 assert.Equal(t, expected, count) 431 }) 432 433 t.Run("boolean props", func(t *testing.T) { 434 isCapital := result.Get("Aggregate", "City").AsSlice()[0].(map[string]interface{})["isCapital"] 435 expected := map[string]interface{}{ 436 "count": json.Number("1"), 437 "percentageTrue": json.Number("1"), 438 "percentageFalse": json.Number("0"), 439 "totalTrue": json.Number("1"), 440 "totalFalse": json.Number("0"), 441 "type": "boolean", 442 } 443 assert.Equal(t, expected, isCapital) 444 }) 445 446 t.Run("int/number props", func(t *testing.T) { 447 population := result.Get("Aggregate", "City").AsSlice()[0].(map[string]interface{})["population"] 448 expected := map[string]interface{}{ 449 "mean": json.Number("3470000"), 450 "count": json.Number("1"), 451 "maximum": json.Number("3470000"), 452 "minimum": json.Number("3470000"), 453 "sum": json.Number("3470000"), 454 "type": "int", 455 } 456 assert.Equal(t, expected, population) 457 }) 458 459 t.Run("ref prop", func(t *testing.T) { 460 inCountry := result.Get("Aggregate", "City").AsSlice()[0].(map[string]interface{})["inCountry"] 461 expected := map[string]interface{}{ 462 "pointingTo": []interface{}{"Country"}, 463 "type": "cref", 464 } 465 assert.Equal(t, expected, inCountry) 466 }) 467 468 t.Run("string prop", func(t *testing.T) { 469 name := result.Get("Aggregate", "City"). 470 AsSlice()[0].(map[string]interface{})["name"].(map[string]interface{}) 471 typeField := name["type"] 472 topOccurrences := name["topOccurrences"] 473 474 assert.Equal(t, schema.DataTypeText.String(), typeField) 475 476 expectedTopOccurrences := []interface{}{ 477 map[string]interface{}{ 478 "value": "Berlin", 479 "occurs": json.Number("1"), 480 }, 481 } 482 assert.ElementsMatch(t, expectedTopOccurrences, topOccurrences) 483 }) 484 }) 485 } 486 487 func localMetaWithNearVectorFilter(t *testing.T) { 488 t.Run("with distance", func(t *testing.T) { 489 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 490 { 491 Aggregate{ 492 CustomVectorClass( 493 nearVector: { 494 vector: [1,0,0] 495 distance: 0.0002 496 } 497 ){ 498 meta { 499 count 500 } 501 name { 502 topOccurrences { 503 occurs 504 value 505 } 506 type 507 count 508 } 509 } 510 } 511 }`) 512 513 t.Run("meta count", func(t *testing.T) { 514 meta := result.Get("Aggregate", "CustomVectorClass").AsSlice()[0].(map[string]interface{})["meta"] 515 count := meta.(map[string]interface{})["count"] 516 expected := json.Number("1") 517 assert.Equal(t, expected, count) 518 }) 519 520 t.Run("string prop", func(t *testing.T) { 521 name := result.Get("Aggregate", "CustomVectorClass"). 522 AsSlice()[0].(map[string]interface{})["name"].(map[string]interface{}) 523 typeField := name["type"] 524 topOccurrences := name["topOccurrences"] 525 526 assert.Equal(t, schema.DataTypeText.String(), typeField) 527 528 expectedTopOccurrences := []interface{}{ 529 map[string]interface{}{ 530 "value": "Mercedes", 531 "occurs": json.Number("1"), 532 }, 533 } 534 assert.ElementsMatch(t, expectedTopOccurrences, topOccurrences) 535 }) 536 }) 537 538 t.Run("with certainty", func(t *testing.T) { 539 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 540 { 541 Aggregate{ 542 CustomVectorClass( 543 nearVector: { 544 vector: [1,0,0] 545 certainty: 0.9999 546 } 547 ){ 548 meta { 549 count 550 } 551 name { 552 topOccurrences { 553 occurs 554 value 555 } 556 type 557 count 558 } 559 } 560 } 561 }`) 562 563 t.Run("meta count", func(t *testing.T) { 564 meta := result.Get("Aggregate", "CustomVectorClass").AsSlice()[0].(map[string]interface{})["meta"] 565 count := meta.(map[string]interface{})["count"] 566 expected := json.Number("1") 567 assert.Equal(t, expected, count) 568 }) 569 570 t.Run("string prop", func(t *testing.T) { 571 name := result.Get("Aggregate", "CustomVectorClass"). 572 AsSlice()[0].(map[string]interface{})["name"].(map[string]interface{}) 573 typeField := name["type"] 574 topOccurrences := name["topOccurrences"] 575 576 assert.Equal(t, schema.DataTypeText.String(), typeField) 577 578 expectedTopOccurrences := []interface{}{ 579 map[string]interface{}{ 580 "value": "Mercedes", 581 "occurs": json.Number("1"), 582 }, 583 } 584 assert.ElementsMatch(t, expectedTopOccurrences, topOccurrences) 585 }) 586 }) 587 } 588 589 func localMetaWithWhereAndNearVectorFilters(t *testing.T) { 590 t.Run("with distance", func(t *testing.T) { 591 t.Run("with expected results, low certainty", func(t *testing.T) { 592 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 593 { 594 Aggregate { 595 CustomVectorClass( 596 where: { 597 valueText: "Ford" 598 operator: Equal 599 path: ["name"] 600 } 601 nearVector: { 602 vector: [1,0,0] 603 distance: 0.6 604 } 605 ) { 606 meta { 607 count 608 } 609 name { 610 topOccurrences { 611 occurs 612 value 613 } 614 type 615 count 616 } 617 } 618 } 619 } 620 `) 621 622 require.NotNil(t, result) 623 624 agg := result.Result.(map[string]interface{})["Aggregate"].(map[string]interface{}) 625 cls := agg["CustomVectorClass"].([]interface{}) 626 require.Len(t, cls, 1) 627 name := cls[0].(map[string]interface{})["name"].(map[string]interface{}) 628 topOcc := name["topOccurrences"].([]interface{}) 629 require.Len(t, topOcc, 1) 630 val := topOcc[0].(map[string]interface{})["value"] 631 assert.Equal(t, "Ford", val) 632 }) 633 634 t.Run("with no expected results, low distance", func(t *testing.T) { 635 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 636 { 637 Aggregate { 638 CustomVectorClass( 639 where: { 640 valueText: "Ford" 641 operator: Equal 642 path: ["name"] 643 } 644 nearVector: { 645 vector: [1,0,0] 646 distance: 0.2 647 } 648 ) { 649 meta { 650 count 651 } 652 name { 653 topOccurrences { 654 occurs 655 value 656 } 657 type 658 count 659 } 660 } 661 } 662 } 663 `) 664 665 require.NotNil(t, result) 666 667 agg := result.Result.(map[string]interface{})["Aggregate"].(map[string]interface{}) 668 cls := agg["CustomVectorClass"].([]interface{}) 669 require.Len(t, cls, 1) 670 name := cls[0].(map[string]interface{})["name"].(map[string]interface{}) 671 topOcc := name["topOccurrences"].([]interface{}) 672 require.Len(t, topOcc, 0) 673 }) 674 675 t.Run("with expected results, low distance", func(t *testing.T) { 676 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 677 { 678 Aggregate { 679 CustomVectorClass( 680 where: { 681 valueText: "Mercedes" 682 operator: Equal 683 path: ["name"] 684 } 685 nearVector: { 686 vector: [1,0,0] 687 distance: 0.1 688 } 689 ) { 690 meta { 691 count 692 } 693 name { 694 topOccurrences { 695 occurs 696 value 697 } 698 type 699 count 700 } 701 } 702 } 703 }`) 704 705 require.NotNil(t, result) 706 707 agg := result.Result.(map[string]interface{})["Aggregate"].(map[string]interface{}) 708 cls := agg["CustomVectorClass"].([]interface{}) 709 require.Len(t, cls, 1) 710 name := cls[0].(map[string]interface{})["name"].(map[string]interface{}) 711 topOcc := name["topOccurrences"].([]interface{}) 712 require.Len(t, topOcc, 1) 713 val := topOcc[0].(map[string]interface{})["value"] 714 assert.Equal(t, "Mercedes", val) 715 }) 716 }) 717 718 t.Run("with certainty", func(t *testing.T) { 719 t.Run("with expected results, low certainty", func(t *testing.T) { 720 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 721 { 722 Aggregate { 723 CustomVectorClass( 724 where: { 725 valueText: "Ford" 726 operator: Equal 727 path: ["name"] 728 } 729 nearVector: { 730 vector: [1,0,0] 731 certainty: 0.7 732 } 733 ) { 734 meta { 735 count 736 } 737 name { 738 topOccurrences { 739 occurs 740 value 741 } 742 type 743 count 744 } 745 } 746 } 747 } 748 `) 749 750 require.NotNil(t, result) 751 752 agg := result.Result.(map[string]interface{})["Aggregate"].(map[string]interface{}) 753 cls := agg["CustomVectorClass"].([]interface{}) 754 require.Len(t, cls, 1) 755 name := cls[0].(map[string]interface{})["name"].(map[string]interface{}) 756 topOcc := name["topOccurrences"].([]interface{}) 757 require.Len(t, topOcc, 1) 758 val := topOcc[0].(map[string]interface{})["value"] 759 assert.Equal(t, "Ford", val) 760 }) 761 762 t.Run("with no expected results, high certainty", func(t *testing.T) { 763 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 764 { 765 Aggregate { 766 CustomVectorClass( 767 where: { 768 valueText: "Ford" 769 operator: Equal 770 path: ["name"] 771 } 772 nearVector: { 773 vector: [1,0,0] 774 certainty: 0.9 775 } 776 ) { 777 meta { 778 count 779 } 780 name { 781 topOccurrences { 782 occurs 783 value 784 } 785 type 786 count 787 } 788 } 789 } 790 } 791 `) 792 793 require.NotNil(t, result) 794 795 agg := result.Result.(map[string]interface{})["Aggregate"].(map[string]interface{}) 796 cls := agg["CustomVectorClass"].([]interface{}) 797 require.Len(t, cls, 1) 798 name := cls[0].(map[string]interface{})["name"].(map[string]interface{}) 799 topOcc := name["topOccurrences"].([]interface{}) 800 require.Len(t, topOcc, 0) 801 }) 802 803 t.Run("with expected results, high certainty", func(t *testing.T) { 804 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 805 { 806 Aggregate { 807 CustomVectorClass( 808 where: { 809 valueText: "Mercedes" 810 operator: Equal 811 path: ["name"] 812 } 813 nearVector: { 814 vector: [1,0,0] 815 certainty: 0.9 816 } 817 ) { 818 meta { 819 count 820 } 821 name { 822 topOccurrences { 823 occurs 824 value 825 } 826 type 827 count 828 } 829 } 830 } 831 } 832 `) 833 834 require.NotNil(t, result) 835 836 agg := result.Result.(map[string]interface{})["Aggregate"].(map[string]interface{}) 837 cls := agg["CustomVectorClass"].([]interface{}) 838 require.Len(t, cls, 1) 839 name := cls[0].(map[string]interface{})["name"].(map[string]interface{}) 840 topOcc := name["topOccurrences"].([]interface{}) 841 require.Len(t, topOcc, 1) 842 val := topOcc[0].(map[string]interface{})["value"] 843 assert.Equal(t, "Mercedes", val) 844 }) 845 }) 846 } 847 848 func localMetaWithWhereGroupByNearMediaFilters(t *testing.T) { 849 t.Run("with nearObject", func(t *testing.T) { 850 query := ` 851 { 852 Aggregate { 853 Company 854 ( 855 groupBy: "name" 856 nearObject: {id: "cfa3b21e-ca4f-4db7-a432-7fc6a23c534d", certainty: 0.99} 857 ) 858 { 859 groupedBy { 860 value 861 } 862 meta { 863 count 864 } 865 } 866 } 867 }` 868 869 expected := map[string]interface{}{ 870 "Aggregate": map[string]interface{}{ 871 "Company": []interface{}{ 872 map[string]interface{}{ 873 "groupedBy": map[string]interface{}{ 874 "value": "Microsoft Inc.", 875 }, 876 "meta": map[string]interface{}{ 877 "count": json.Number("1"), 878 }, 879 }, 880 }, 881 }, 882 } 883 884 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query).Result 885 assert.EqualValues(t, expected, result) 886 }) 887 888 t.Run("with nearText", func(t *testing.T) { 889 t.Run("with distance", func(t *testing.T) { 890 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 891 { 892 Aggregate{ 893 City ( 894 groupBy: "population" 895 where: { 896 valueBoolean: true, 897 operator: Equal, 898 path: ["isCapital"] 899 } 900 nearText: { 901 concepts: ["Amsterdam"] 902 distance: 0.2 903 } 904 ){ 905 meta { 906 count 907 } 908 groupedBy { 909 value 910 } 911 } 912 } 913 } 914 `) 915 916 expected := map[string]interface{}{ 917 "Aggregate": map[string]interface{}{ 918 "City": []interface{}{ 919 map[string]interface{}{ 920 "groupedBy": map[string]interface{}{ 921 "value": "1.8e+06", 922 }, 923 "meta": map[string]interface{}{ 924 "count": json.Number("1"), 925 }, 926 }, 927 }, 928 }, 929 } 930 931 assert.EqualValues(t, expected, result.Result) 932 }) 933 934 t.Run("with certainty", func(t *testing.T) { 935 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 936 { 937 Aggregate{ 938 City ( 939 groupBy: "population" 940 where: { 941 valueBoolean: true, 942 operator: Equal, 943 path: ["isCapital"] 944 } 945 nearText: { 946 concepts: ["Amsterdam"] 947 certainty: 0.9 948 } 949 ){ 950 meta { 951 count 952 } 953 groupedBy { 954 value 955 } 956 } 957 } 958 } 959 `) 960 961 expected := map[string]interface{}{ 962 "Aggregate": map[string]interface{}{ 963 "City": []interface{}{ 964 map[string]interface{}{ 965 "groupedBy": map[string]interface{}{ 966 "value": "1.8e+06", 967 }, 968 "meta": map[string]interface{}{ 969 "count": json.Number("1"), 970 }, 971 }, 972 }, 973 }, 974 } 975 976 assert.EqualValues(t, expected, result.Result) 977 }) 978 }) 979 980 t.Run("with nearVector", func(t *testing.T) { 981 getQuery := ` 982 { 983 Get { 984 Company(where: { 985 path: ["name"] 986 operator: Equal 987 valueText: "Google Inc." 988 }) 989 { 990 _additional { 991 vector 992 } 993 } 994 } 995 }` 996 997 vectorResult := graphqlhelper.AssertGraphQL(t, helper.RootAuth, getQuery). 998 Get("Get", "Company"). 999 AsSlice()[0].(map[string]interface{})["_additional"].(map[string]interface{})["vector"].([]interface{}) 1000 1001 vector := make([]float32, len(vectorResult)) 1002 for i, ifc := range vectorResult { 1003 val, err := strconv.ParseFloat(ifc.(json.Number).String(), 32) 1004 require.Nil(t, err) 1005 vector[i] = float32(val) 1006 } 1007 1008 aggQuery := fmt.Sprintf(` 1009 { 1010 Aggregate { 1011 Company 1012 ( 1013 groupBy: "name" 1014 nearVector: {vector: %+v, certainty: 0.99} 1015 ) 1016 { 1017 groupedBy { 1018 value 1019 } 1020 meta { 1021 count 1022 } 1023 } 1024 } 1025 } 1026 `, vector) 1027 1028 aggResult := graphqlhelper.AssertGraphQL(t, helper.RootAuth, aggQuery).Result 1029 1030 expected := map[string]interface{}{ 1031 "Aggregate": map[string]interface{}{ 1032 "Company": []interface{}{ 1033 map[string]interface{}{ 1034 "groupedBy": map[string]interface{}{ 1035 "value": "Google Inc.", 1036 }, 1037 "meta": map[string]interface{}{ 1038 "count": json.Number("1"), 1039 }, 1040 }, 1041 }, 1042 }, 1043 } 1044 1045 assert.EqualValues(t, expected, aggResult) 1046 }) 1047 } 1048 1049 func localMetaWithObjectLimit(t *testing.T) { 1050 t.Run("with nearObject and distance", func(t *testing.T) { 1051 objectLimit := 1 1052 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, fmt.Sprintf(` 1053 { 1054 Aggregate{ 1055 City ( 1056 objectLimit: %d 1057 nearObject: { 1058 id: "9b9cbea5-e87e-4cd0-89af-e2f424fd52d6" 1059 distance: 0.3 1060 } 1061 ){ 1062 meta { 1063 count 1064 } 1065 } 1066 } 1067 } 1068 `, objectLimit)) 1069 1070 t.Run("validate objectLimit functions as expected", func(t *testing.T) { 1071 res := result.Get("Aggregate", "City").AsSlice() 1072 require.Len(t, res, 1) 1073 meta := res[0].(map[string]interface{})["meta"] 1074 count := meta.(map[string]interface{})["count"] 1075 assert.Equal(t, json.Number(fmt.Sprint(objectLimit)), count) 1076 }) 1077 }) 1078 1079 t.Run("with nearObject and certainty", func(t *testing.T) { 1080 objectLimit := 1 1081 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, fmt.Sprintf(` 1082 { 1083 Aggregate{ 1084 City ( 1085 objectLimit: %d 1086 nearObject: { 1087 id: "9b9cbea5-e87e-4cd0-89af-e2f424fd52d6" 1088 certainty: 0.7 1089 } 1090 ){ 1091 meta { 1092 count 1093 } 1094 } 1095 } 1096 } 1097 `, objectLimit)) 1098 1099 t.Run("validate objectLimit functions as expected", func(t *testing.T) { 1100 res := result.Get("Aggregate", "City").AsSlice() 1101 require.Len(t, res, 1) 1102 meta := res[0].(map[string]interface{})["meta"] 1103 count := meta.(map[string]interface{})["count"] 1104 assert.Equal(t, json.Number(fmt.Sprint(objectLimit)), count) 1105 }) 1106 }) 1107 1108 t.Run("with nearObject and no certainty", func(t *testing.T) { 1109 objectLimit := 2 1110 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, fmt.Sprintf(` 1111 { 1112 Aggregate{ 1113 City ( 1114 objectLimit: %d 1115 nearObject: { 1116 id: "9b9cbea5-e87e-4cd0-89af-e2f424fd52d6" 1117 } 1118 ){ 1119 meta { 1120 count 1121 } 1122 } 1123 } 1124 } 1125 `, objectLimit)) 1126 1127 t.Run("validate objectLimit functions as expected", func(t *testing.T) { 1128 res := result.Get("Aggregate", "City").AsSlice() 1129 require.Len(t, res, 1) 1130 meta := res[0].(map[string]interface{})["meta"] 1131 count := meta.(map[string]interface{})["count"] 1132 assert.Equal(t, json.Number(fmt.Sprint(objectLimit)), count) 1133 }) 1134 }) 1135 1136 t.Run("with nearObject and very high distance, no objectLimit", func(t *testing.T) { 1137 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 1138 { 1139 Aggregate { 1140 RansomNote( 1141 nearText: { 1142 concepts: ["abc"] 1143 distance: 1.9998 1144 } 1145 ) { 1146 meta { 1147 count 1148 } 1149 } 1150 } 1151 } 1152 `) 1153 1154 t.Run("validate nearMedia runs unlimited without objectLimit", func(t *testing.T) { 1155 res := result.Get("Aggregate", "RansomNote").AsSlice() 1156 require.Len(t, res, 1) 1157 meta := res[0].(map[string]interface{})["meta"] 1158 count := meta.(map[string]interface{})["count"] 1159 assert.Equal(t, json.Number("500"), count) 1160 }) 1161 }) 1162 1163 t.Run("with nearObject and very low certainty, no objectLimit", func(t *testing.T) { 1164 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 1165 { 1166 Aggregate { 1167 RansomNote( 1168 nearText: { 1169 concepts: ["abc"] 1170 certainty: 0.0001 1171 } 1172 ) { 1173 meta { 1174 count 1175 } 1176 } 1177 } 1178 } 1179 `) 1180 1181 t.Run("validate nearMedia runs unlimited without objectLimit", func(t *testing.T) { 1182 res := result.Get("Aggregate", "RansomNote").AsSlice() 1183 require.Len(t, res, 1) 1184 meta := res[0].(map[string]interface{})["meta"] 1185 count := meta.(map[string]interface{})["count"] 1186 assert.Equal(t, json.Number("500"), count) 1187 }) 1188 }) 1189 1190 t.Run("with nearObject and low distance (few results), high objectLimit", func(t *testing.T) { 1191 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 1192 { 1193 Aggregate { 1194 RansomNote( 1195 nearText: { 1196 concepts: ["abc"] 1197 distance: 0.6 # should return about 6 elements 1198 } 1199 objectLimit:100, 1200 ) { 1201 meta { 1202 count 1203 } 1204 } 1205 } 1206 } 1207 `) 1208 1209 t.Run("validate fewer than objectLimit elements are returned", func(t *testing.T) { 1210 res := result.Get("Aggregate", "RansomNote").AsSlice() 1211 require.Len(t, res, 1) 1212 meta := res[0].(map[string]interface{})["meta"] 1213 count := meta.(map[string]interface{})["count"] 1214 countParsed, err := count.(json.Number).Int64() 1215 require.Nil(t, err) 1216 assert.Less(t, countParsed, int64(100)) 1217 }) 1218 }) 1219 1220 t.Run("with nearObject and high certainty (few results), high objectLimit", func(t *testing.T) { 1221 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, ` 1222 { 1223 Aggregate { 1224 RansomNote( 1225 nearText: { 1226 concepts: ["abc"] 1227 certainty: 0.7 # should return about 6 elements 1228 } 1229 objectLimit:100, 1230 ) { 1231 meta { 1232 count 1233 } 1234 } 1235 } 1236 } 1237 `) 1238 1239 t.Run("validate fewer than objectLimit elements are returned", func(t *testing.T) { 1240 res := result.Get("Aggregate", "RansomNote").AsSlice() 1241 require.Len(t, res, 1) 1242 meta := res[0].(map[string]interface{})["meta"] 1243 count := meta.(map[string]interface{})["count"] 1244 countParsed, err := count.(json.Number).Int64() 1245 require.Nil(t, err) 1246 assert.Less(t, countParsed, int64(100)) 1247 }) 1248 }) 1249 1250 t.Run("with nearText and no distance/certainty, where filter and groupBy", func(t *testing.T) { 1251 objectLimit := 4 1252 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, fmt.Sprintf(` 1253 { 1254 Aggregate { 1255 Company ( 1256 groupBy: ["name"] 1257 where: { 1258 valueText: "Apple*", 1259 operator: Like, 1260 path: ["name"] 1261 } 1262 objectLimit: %d 1263 nearText: { 1264 concepts: ["Apple"] 1265 certainty: 0.5 1266 } 1267 ){ 1268 meta { 1269 count 1270 } 1271 groupedBy { 1272 value 1273 } 1274 } 1275 } 1276 } 1277 `, objectLimit)) 1278 1279 expected := []interface{}{ 1280 map[string]interface{}{ 1281 "groupedBy": map[string]interface{}{ 1282 "value": "Apple Incorporated", 1283 }, 1284 "meta": map[string]interface{}{ 1285 "count": json.Number("1"), 1286 }, 1287 }, 1288 map[string]interface{}{ 1289 "groupedBy": map[string]interface{}{ 1290 "value": "Apple Inc.", 1291 }, 1292 "meta": map[string]interface{}{ 1293 "count": json.Number("1"), 1294 }, 1295 }, 1296 map[string]interface{}{ 1297 "groupedBy": map[string]interface{}{ 1298 "value": "Apple", 1299 }, 1300 "meta": map[string]interface{}{ 1301 "count": json.Number("1"), 1302 }, 1303 }, 1304 } 1305 1306 companies := result.Get("Aggregate", "Company").Result.([]interface{}) 1307 for _, company := range companies { 1308 assert.Contains(t, expected, company) 1309 } 1310 }) 1311 1312 t.Run("with nearObject and certainty, where filter", func(t *testing.T) { 1313 objectLimit := 1 1314 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, fmt.Sprintf(` 1315 { 1316 Aggregate{ 1317 City ( 1318 where: { 1319 valueBoolean: true, 1320 operator: Equal, 1321 path: ["isCapital"] 1322 } 1323 objectLimit: %d 1324 nearObject: { 1325 id: "9b9cbea5-e87e-4cd0-89af-e2f424fd52d6" 1326 } 1327 ){ 1328 meta { 1329 count 1330 } 1331 } 1332 } 1333 } 1334 `, objectLimit)) 1335 1336 t.Run("validate objectLimit functions as expected", func(t *testing.T) { 1337 res := result.Get("Aggregate", "City").AsSlice() 1338 require.Len(t, res, 1) 1339 meta := res[0].(map[string]interface{})["meta"] 1340 count := meta.(map[string]interface{})["count"] 1341 assert.Equal(t, json.Number(fmt.Sprint(objectLimit)), count) 1342 }) 1343 }) 1344 } 1345 1346 func aggregatesOnDateFields(t *testing.T) { 1347 t.Run("without grouping", func(t *testing.T) { 1348 query := ` 1349 { 1350 Aggregate { 1351 HasDateField { 1352 timestamp { 1353 count 1354 minimum 1355 maximum 1356 median 1357 } 1358 } 1359 } 1360 }` 1361 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query).Get("Aggregate", "HasDateField").AsSlice() 1362 assert.Len(t, result, 1) 1363 1364 expected := []interface{}{ 1365 map[string]interface{}{ 1366 "timestamp": map[string]interface{}{ 1367 "count": json.Number("10"), 1368 "maximum": "2022-06-16T22:19:11.837473Z", 1369 "median": "2022-06-16T22:19:06.1449075Z", 1370 "minimum": "2022-06-16T22:18:59.640162Z", 1371 }, 1372 }, 1373 } 1374 assert.Equal(t, expected, result) 1375 }) 1376 1377 t.Run("with grouping on a unique field", func(t *testing.T) { 1378 query := ` 1379 { 1380 Aggregate { 1381 HasDateField 1382 ( 1383 groupBy: "unique" 1384 ) 1385 { 1386 timestamp { 1387 count 1388 minimum 1389 maximum 1390 median 1391 mode 1392 } 1393 } 1394 } 1395 }` 1396 1397 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query).Get("Aggregate", "HasDateField").AsSlice() 1398 assert.Len(t, result, 10) 1399 1400 expected := []interface{}{ 1401 map[string]interface{}{ 1402 "timestamp": map[string]interface{}{ 1403 "count": json.Number("1"), 1404 "maximum": "2022-06-16T22:19:05.894857Z", 1405 "median": "2022-06-16T22:19:05.894857Z", 1406 "minimum": "2022-06-16T22:19:05.894857Z", 1407 "mode": "2022-06-16T22:19:05.894857Z", 1408 }, 1409 }, 1410 map[string]interface{}{ 1411 "timestamp": map[string]interface{}{ 1412 "count": json.Number("1"), 1413 "maximum": "2022-06-16T22:19:08.112395Z", 1414 "median": "2022-06-16T22:19:08.112395Z", 1415 "minimum": "2022-06-16T22:19:08.112395Z", 1416 "mode": "2022-06-16T22:19:08.112395Z", 1417 }, 1418 }, 1419 map[string]interface{}{ 1420 "timestamp": map[string]interface{}{ 1421 "count": json.Number("1"), 1422 "maximum": "2022-06-16T22:19:03.495596Z", 1423 "median": "2022-06-16T22:19:03.495596Z", 1424 "minimum": "2022-06-16T22:19:03.495596Z", 1425 "mode": "2022-06-16T22:19:03.495596Z", 1426 }, 1427 }, 1428 map[string]interface{}{ 1429 "timestamp": map[string]interface{}{ 1430 "count": json.Number("1"), 1431 "maximum": "2022-06-16T22:19:07.589828Z", 1432 "median": "2022-06-16T22:19:07.589828Z", 1433 "minimum": "2022-06-16T22:19:07.589828Z", 1434 "mode": "2022-06-16T22:19:07.589828Z", 1435 }, 1436 }, 1437 map[string]interface{}{ 1438 "timestamp": map[string]interface{}{ 1439 "count": json.Number("1"), 1440 "maximum": "2022-06-16T22:19:06.394958Z", 1441 "median": "2022-06-16T22:19:06.394958Z", 1442 "minimum": "2022-06-16T22:19:06.394958Z", 1443 "mode": "2022-06-16T22:19:06.394958Z", 1444 }, 1445 }, 1446 map[string]interface{}{ 1447 "timestamp": map[string]interface{}{ 1448 "count": json.Number("1"), 1449 "maximum": "2022-06-16T22:19:11.837473Z", 1450 "median": "2022-06-16T22:19:11.837473Z", 1451 "minimum": "2022-06-16T22:19:11.837473Z", 1452 "mode": "2022-06-16T22:19:11.837473Z", 1453 }, 1454 }, 1455 map[string]interface{}{ 1456 "timestamp": map[string]interface{}{ 1457 "count": json.Number("1"), 1458 "maximum": "2022-06-16T22:18:59.640162Z", 1459 "median": "2022-06-16T22:18:59.640162Z", 1460 "minimum": "2022-06-16T22:18:59.640162Z", 1461 "mode": "2022-06-16T22:18:59.640162Z", 1462 }, 1463 }, 1464 map[string]interface{}{ 1465 "timestamp": map[string]interface{}{ 1466 "count": json.Number("1"), 1467 "maximum": "2022-06-16T22:19:01.495967Z", 1468 "median": "2022-06-16T22:19:01.495967Z", 1469 "minimum": "2022-06-16T22:19:01.495967Z", 1470 "mode": "2022-06-16T22:19:01.495967Z", 1471 }, 1472 }, 1473 map[string]interface{}{ 1474 "timestamp": map[string]interface{}{ 1475 "count": json.Number("1"), 1476 "maximum": "2022-06-16T22:19:10.339493Z", 1477 "median": "2022-06-16T22:19:10.339493Z", 1478 "minimum": "2022-06-16T22:19:10.339493Z", 1479 "mode": "2022-06-16T22:19:10.339493Z", 1480 }, 1481 }, 1482 map[string]interface{}{ 1483 "timestamp": map[string]interface{}{ 1484 "count": json.Number("1"), 1485 "maximum": "2022-06-16T22:19:04.3828349Z", 1486 "median": "2022-06-16T22:19:04.3828349Z", 1487 "minimum": "2022-06-16T22:19:04.3828349Z", 1488 "mode": "2022-06-16T22:19:04.3828349Z", 1489 }, 1490 }, 1491 } 1492 1493 for _, res := range result { 1494 assert.Contains(t, expected, res) 1495 } 1496 }) 1497 1498 t.Run("group on identical field", func(t *testing.T) { 1499 query := ` 1500 { 1501 Aggregate { 1502 HasDateField 1503 ( 1504 groupBy: "identical" 1505 ) 1506 { 1507 timestamp { 1508 count 1509 minimum 1510 maximum 1511 median 1512 } 1513 } 1514 } 1515 }` 1516 1517 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query).Get("Aggregate", "HasDateField").AsSlice() 1518 1519 expected := []interface{}{ 1520 map[string]interface{}{ 1521 "timestamp": map[string]interface{}{ 1522 "count": json.Number("10"), 1523 "maximum": "2022-06-16T22:19:11.837473Z", 1524 "median": "2022-06-16T22:19:06.1449075Z", 1525 "minimum": "2022-06-16T22:18:59.640162Z", 1526 }, 1527 }, 1528 } 1529 1530 assert.Equal(t, expected, result) 1531 }) 1532 }