github.com/unigraph-dev/dgraph@v1.1.1-0.20200923154953-8b52b426f765/query/query_facets_test.go (about) 1 /* 2 * Copyright 2017-2018 Dgraph Labs, Inc. and Contributors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package query 18 19 import ( 20 "context" 21 "fmt" 22 "testing" 23 24 "github.com/stretchr/testify/require" 25 ) 26 27 var ( 28 facetSetupDone = false 29 ) 30 31 func populateClusterWithFacets() { 32 // Return immediately if the setup has been performed already. 33 if facetSetupDone { 34 return 35 } 36 37 triples := ` 38 <25> <name> "Daryl Dixon" . 39 <31> <name> "Andrea" . 40 <33> <name> "Michale" . 41 <320> <name> "Test facet"@en (type = "Test facet with lang") . 42 43 <31> <friend> <24> . 44 45 <33> <schools> <2433> . 46 47 <1> <gender> "female" . 48 <23> <gender> "male" . 49 50 <202> <model> "Prius" (type = "Electric") . 51 ` 52 53 friendFacets1 := "(since = 2006-01-02T15:04:05)" 54 friendFacets2 := "(since = 2005-05-02T15:04:05, close = true, family = false, age = 33)" 55 friendFacets3 := "(since = 2004-05-02T15:04:05, close = true, family = true, tag = \"Domain3\")" 56 friendFacets4 := "(since = 2007-05-02T15:04:05, close = false, family = true, tag = 34)" 57 friendFacets5 := "(games = \"football basketball chess tennis\", close = false, age = 35)" 58 friendFacets6 := "(games = \"football basketball hockey\", close = false)" 59 60 triples += fmt.Sprintf("<1> <friend> <23> %s .\n", friendFacets1) 61 triples += fmt.Sprintf("<1> <friend> <24> %s .\n", friendFacets3) 62 triples += fmt.Sprintf("<1> <friend> <25> %s .\n", friendFacets4) 63 triples += fmt.Sprintf("<1> <friend> <31> %s .\n", friendFacets1) 64 triples += fmt.Sprintf("<1> <friend> <101> %s .\n", friendFacets2) 65 triples += fmt.Sprintf("<23> <friend> <1> %s .\n", friendFacets1) 66 triples += fmt.Sprintf("<31> <friend> <1> %s .\n", friendFacets5) 67 triples += fmt.Sprintf("<31> <friend> <25> %s .\n", friendFacets6) 68 69 nameFacets := "(origin = \"french\")" 70 triples += fmt.Sprintf("<1> <name> \"Michonne\" %s .\n", nameFacets) 71 triples += fmt.Sprintf("<23> <name> \"Rick Grimes\" %s .\n", nameFacets) 72 triples += fmt.Sprintf("<24> <name> \"Glenn Rhee\" %s .\n", nameFacets) 73 74 addTriplesToCluster(triples) 75 76 // Mark the setup as done so that the next tests do not have to perform it. 77 facetSetupDone = true 78 } 79 80 func TestRetrieveFacetsSimple(t *testing.T) { 81 populateClusterWithFacets() 82 query := ` 83 { 84 me(func: uid(0x1)) { 85 name @facets 86 gender @facets 87 } 88 } 89 ` 90 91 js := processQueryNoErr(t, query) 92 require.JSONEq(t, 93 `{"data":{"me":[{"name|origin":"french","name":"Michonne","gender":"female"}]}}`, 94 js) 95 } 96 97 func TestOrderFacets(t *testing.T) { 98 populateClusterWithFacets() 99 // to see how friend @facets are positioned in output. 100 query := ` 101 { 102 me(func: uid(1)) { 103 friend @facets(orderasc:since) { 104 name 105 } 106 } 107 } 108 ` 109 110 js := processQueryNoErr(t, query) 111 require.JSONEq(t, 112 `{"data":{"me":[{"friend":[{"name":"Glenn Rhee","friend|since":"2004-05-02T15:04:05Z"},{"friend|since":"2005-05-02T15:04:05Z"},{"name":"Rick Grimes","friend|since":"2006-01-02T15:04:05Z"},{"name":"Andrea","friend|since":"2006-01-02T15:04:05Z"},{"name":"Daryl Dixon","friend|since":"2007-05-02T15:04:05Z"}]}]}}`, 113 js) 114 } 115 116 func TestOrderdescFacets(t *testing.T) { 117 populateClusterWithFacets() 118 // to see how friend @facets are positioned in output. 119 query := ` 120 { 121 me(func: uid(1)) { 122 friend @facets(orderdesc:since) { 123 name 124 } 125 } 126 } 127 ` 128 129 js := processQueryNoErr(t, query) 130 require.JSONEq(t, 131 `{"data":{"me":[{"friend":[{"name":"Daryl Dixon","friend|since":"2007-05-02T15:04:05Z"},{"name":"Rick Grimes","friend|since":"2006-01-02T15:04:05Z"},{"name":"Andrea","friend|since":"2006-01-02T15:04:05Z"},{"friend|since":"2005-05-02T15:04:05Z"},{"name":"Glenn Rhee","friend|since":"2004-05-02T15:04:05Z"}]}]}}`, 132 js) 133 } 134 135 func TestOrderdescFacetsWithFilters(t *testing.T) { 136 populateClusterWithFacets() 137 query := ` 138 { 139 140 var(func: uid(1)) { 141 f as friend 142 } 143 144 me(func: uid(1)) { 145 friend @filter(uid(f)) @facets(orderdesc:since) { 146 name 147 } 148 } 149 } 150 ` 151 152 js := processQueryNoErr(t, query) 153 require.JSONEq(t, 154 `{"data":{"me":[{"friend":[{"name":"Daryl Dixon","friend|since":"2007-05-02T15:04:05Z"},{"name":"Rick Grimes","friend|since":"2006-01-02T15:04:05Z"},{"name":"Andrea","friend|since":"2006-01-02T15:04:05Z"},{"friend|since":"2005-05-02T15:04:05Z"},{"name":"Glenn Rhee","friend|since":"2004-05-02T15:04:05Z"}]}]}}`, 155 js) 156 } 157 158 func TestRetrieveFacetsAsVars(t *testing.T) { 159 populateClusterWithFacets() 160 // to see how friend @facets are positioned in output. 161 query := ` 162 { 163 var(func: uid(0x1)) { 164 friend @facets(a as since) 165 } 166 167 me(func: uid( 23)) { 168 name 169 val(a) 170 } 171 } 172 ` 173 174 js := processQueryNoErr(t, query) 175 require.JSONEq(t, 176 `{"data": {"me":[{"name":"Rick Grimes","val(a)":"2006-01-02T15:04:05Z"}]}}`, 177 js) 178 } 179 180 func TestRetrieveFacetsUidValues(t *testing.T) { 181 populateClusterWithFacets() 182 // to see how friend @facets are positioned in output. 183 query := ` 184 { 185 me(func: uid(0x1)) { 186 friend @facets { 187 name @facets 188 } 189 } 190 } 191 ` 192 193 js := processQueryNoErr(t, query) 194 require.JSONEq(t, 195 `{"data":{"me":[{"friend":[{"name|origin":"french","name":"Rick Grimes","friend|since":"2006-01-02T15:04:05Z"},{"name|origin":"french","name":"Glenn Rhee","friend|close":true,"friend|family":true,"friend|since":"2004-05-02T15:04:05Z","friend|tag":"Domain3"},{"name":"Daryl Dixon","friend|close":false,"friend|family":true,"friend|since":"2007-05-02T15:04:05Z","friend|tag":34},{"name":"Andrea","friend|since":"2006-01-02T15:04:05Z"},{"friend|age":33,"friend|close":true,"friend|family":false,"friend|since":"2005-05-02T15:04:05Z"}]}]}}`, 196 js) 197 } 198 199 func TestRetrieveFacetsAll(t *testing.T) { 200 populateClusterWithFacets() 201 query := ` 202 { 203 me(func: uid(0x1)) { 204 name @facets 205 friend @facets { 206 name @facets 207 gender @facets 208 } 209 gender @facets 210 } 211 } 212 ` 213 214 js := processQueryNoErr(t, query) 215 require.JSONEq(t, 216 `{"data":{"me":[{"name|origin":"french","name":"Michonne","friend":[{"name|origin":"french","name":"Rick Grimes","gender":"male","friend|since":"2006-01-02T15:04:05Z"},{"name|origin":"french","name":"Glenn Rhee","friend|close":true,"friend|family":true,"friend|since":"2004-05-02T15:04:05Z","friend|tag":"Domain3"},{"name":"Daryl Dixon","friend|close":false,"friend|family":true,"friend|since":"2007-05-02T15:04:05Z","friend|tag":34},{"name":"Andrea","friend|since":"2006-01-02T15:04:05Z"},{"friend|age":33,"friend|close":true,"friend|family":false,"friend|since":"2005-05-02T15:04:05Z"}],"gender":"female"}]}}`, 217 js) 218 } 219 220 func TestFacetsNotInQuery(t *testing.T) { 221 populateClusterWithFacets() 222 query := ` 223 { 224 me(func: uid(0x1)) { 225 name 226 gender 227 friend { 228 name 229 gender 230 } 231 } 232 } 233 ` 234 235 js := processQueryNoErr(t, query) 236 require.JSONEq(t, 237 `{"data": {"me":[{"friend":[{"gender":"male","name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}],"gender":"female","name":"Michonne"}]}}`, 238 js) 239 } 240 241 func TestSubjectWithNoFacets(t *testing.T) { 242 populateClusterWithFacets() 243 // id 33 does not have any facets associated with name and school 244 query := ` 245 { 246 me(func: uid(0x21)) { 247 name @facets 248 school @facets { 249 name 250 } 251 } 252 } 253 ` 254 js := processQueryNoErr(t, query) 255 require.JSONEq(t, 256 `{"data": {"me":[{"name":"Michale"}]}}`, 257 js) 258 } 259 260 func TestFetchingFewFacets(t *testing.T) { 261 populateClusterWithFacets() 262 // only 1 friend of 1 has facet : "close" and she/he has no name 263 query := ` 264 { 265 me(func: uid(0x1)) { 266 name 267 friend @facets(close) { 268 name 269 } 270 } 271 } 272 ` 273 274 js := processQueryNoErr(t, query) 275 require.JSONEq(t, 276 `{"data":{"me":[{"name":"Michonne","friend":[{"name":"Rick Grimes"},{"name":"Glenn Rhee","friend|close":true},{"name":"Daryl Dixon","friend|close":false},{"name":"Andrea"},{"friend|close":true}]}]}}`, 277 js) 278 } 279 280 func TestFetchingNoFacets(t *testing.T) { 281 populateClusterWithFacets() 282 // TestFetchingFewFacets but without the facet. Returns no facets. 283 query := ` 284 { 285 me(func: uid(0x1)) { 286 name 287 friend @facets() { 288 name 289 } 290 } 291 } 292 ` 293 294 js := processQueryNoErr(t, query) 295 require.JSONEq(t, 296 `{"data": {"me":[{"friend":[{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}],"name":"Michonne"}]}}`, 297 js) 298 } 299 300 func TestFacetsSortOrder(t *testing.T) { 301 populateClusterWithFacets() 302 // order of facets in gql query should not matter. 303 query := ` 304 { 305 me(func: uid(0x1)) { 306 name 307 friend @facets(family, close) { 308 name 309 } 310 } 311 } 312 ` 313 314 js := processQueryNoErr(t, query) 315 require.JSONEq(t, 316 `{"data":{"me":[{"name":"Michonne","friend":[{"name":"Rick Grimes"},{"name":"Glenn Rhee","friend|close":true,"friend|family":true},{"name":"Daryl Dixon","friend|close":false,"friend|family":true},{"name":"Andrea"},{"friend|close":true,"friend|family":false}]}]}}`, 317 js) 318 } 319 320 func TestUnknownFacets(t *testing.T) { 321 populateClusterWithFacets() 322 // uknown facets should be ignored. 323 query := ` 324 { 325 me(func: uid(0x1)) { 326 name 327 friend @facets(unknownfacets1, unknownfacets2) { 328 name 329 } 330 } 331 } 332 ` 333 334 js := processQueryNoErr(t, query) 335 require.JSONEq(t, 336 `{"data": {"me":[{"friend":[{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}],"name":"Michonne"}]}}`, 337 js) 338 } 339 340 func TestFacetsMutation(t *testing.T) { 341 populateClusterWithFacets() 342 343 // Delete friendship between Michonne and Glenn 344 deleteTriplesInCluster("<1> <friend> <24> .") 345 friendFacets := "(since = 2001-11-10T00:00:00Z, close = false, family = false)" 346 // 101 is not close friend now. 347 addTriplesToCluster(fmt.Sprintf(`<1> <friend> <101> %s .`, friendFacets)) 348 // This test messes with the test setup, so set facetSetupDone to false so 349 // the next test redoes the setup. 350 facetSetupDone = false 351 352 query := ` 353 { 354 me(func: uid(0x1)) { 355 name 356 friend @facets { 357 name 358 } 359 } 360 } 361 ` 362 363 js := processQueryNoErr(t, query) 364 require.JSONEq(t, 365 `{"data":{"me":[{"name":"Michonne","friend":[{"name":"Rick Grimes","friend|since":"2006-01-02T15:04:05Z"},{"name":"Daryl Dixon","friend|close":false,"friend|family":true,"friend|since":"2007-05-02T15:04:05Z","friend|tag":34},{"name":"Andrea","friend|since":"2006-01-02T15:04:05Z"},{"friend|close":false,"friend|family":false,"friend|since":"2001-11-10T00:00:00Z"}]}]}}`, 366 js) 367 } 368 369 func TestFacetsFilterSimple(t *testing.T) { 370 populateClusterWithFacets() 371 // find close friends of 1 372 query := ` 373 { 374 me(func: uid(0x1)) { 375 name 376 friend @facets(eq(close, true)) { 377 name 378 uid 379 } 380 } 381 } 382 ` 383 384 js := processQueryNoErr(t, query) 385 // 0x65 does not have name. 386 require.JSONEq(t, 387 `{"data": {"me":[{"friend":[{"uid":"0x18","name":"Glenn Rhee"},{"uid":"0x65"}],"name":"Michonne"}]}}`, 388 js) 389 } 390 391 func TestFacetsFilterSimple2(t *testing.T) { 392 populateClusterWithFacets() 393 // find close friends of 1 394 query := ` 395 { 396 me(func: uid(0x1)) { 397 name 398 friend @facets(eq(tag, "Domain3")) { 399 name 400 uid 401 } 402 } 403 } 404 ` 405 406 js := processQueryNoErr(t, query) 407 require.JSONEq(t, 408 `{"data": {"me":[{"friend":[{"uid":"0x18","name":"Glenn Rhee"}],"name":"Michonne"}]}}`, 409 js) 410 } 411 412 func TestFacetsFilterSimple3(t *testing.T) { 413 populateClusterWithFacets() 414 // find close friends of 1 415 query := ` 416 { 417 me(func: uid(0x1)) { 418 name 419 friend @facets(eq(tag, "34")) { 420 name 421 uid 422 } 423 } 424 } 425 ` 426 427 js := processQueryNoErr(t, query) 428 require.JSONEq(t, 429 `{"data": {"me":[{"friend":[{"uid":"0x19","name":"Daryl Dixon"}],"name":"Michonne"}]}}`, 430 js) 431 } 432 433 func TestFacetsFilterOr(t *testing.T) { 434 populateClusterWithFacets() 435 // find close or family friends of 1 436 query := ` 437 { 438 me(func: uid(0x1)) { 439 name 440 friend @facets(eq(close, true) OR eq(family, true)) { 441 name 442 uid 443 } 444 } 445 } 446 ` 447 448 js := processQueryNoErr(t, query) 449 // 0x65 (101) does not have name. 450 require.JSONEq(t, 451 `{"data": {"me":[{"friend":[{"uid":"0x18","name":"Glenn Rhee"},{"uid":"0x19","name":"Daryl Dixon"},{"uid":"0x65"}],"name":"Michonne"}]}}`, 452 js) 453 } 454 455 func TestFacetsFilterAnd(t *testing.T) { 456 populateClusterWithFacets() 457 // unknown filters do not have any effect on results. 458 query := ` 459 { 460 me(func: uid(0x1)) { 461 name 462 friend @facets(eq(close, true) AND eq(family, false)) { 463 name 464 uid 465 } 466 } 467 } 468 ` 469 470 js := processQueryNoErr(t, query) 471 require.JSONEq(t, 472 `{"data": {"me":[{"friend":[{"uid":"0x65"}],"name":"Michonne"}]}}`, 473 js) 474 } 475 476 func TestFacetsFilterle(t *testing.T) { 477 populateClusterWithFacets() 478 // find friends of 1 below 36 years of age. 479 query := ` 480 { 481 me(func: uid(0x1)) { 482 name 483 friend @facets(le(age, 35)) { 484 name 485 uid 486 } 487 } 488 } 489 ` 490 491 js := processQueryNoErr(t, query) 492 require.JSONEq(t, 493 `{"data": {"me":[{"friend":[{"uid":"0x65"}],"name":"Michonne"}]}}`, 494 js) 495 } 496 497 func TestFacetsFilterge(t *testing.T) { 498 populateClusterWithFacets() 499 // find friends of 1 above 32 years of age. 500 query := ` 501 { 502 me(func: uid(0x1)) { 503 name 504 friend @facets(ge(age, 33)) { 505 name 506 uid 507 } 508 } 509 } 510 ` 511 512 js := processQueryNoErr(t, query) 513 require.JSONEq(t, 514 `{"data": {"me":[{"friend":[{"uid":"0x65"}],"name":"Michonne"}]}}`, 515 js) 516 } 517 518 func TestFacetsFilterAndOrle(t *testing.T) { 519 populateClusterWithFacets() 520 // find close or family friends of 1 before 2007-01-10 521 query := ` 522 { 523 me(func: uid(0x1)) { 524 name 525 friend @facets(eq(close, true) OR eq(family, true) AND le(since, "2007-01-10")) { 526 name 527 uid 528 } 529 } 530 } 531 ` 532 533 js := processQueryNoErr(t, query) 534 // 0x65 (101) does not have name. 535 require.JSONEq(t, 536 `{"data": {"me":[{"friend":[{"uid":"0x18","name":"Glenn Rhee"},{"uid":"0x65"}],"name":"Michonne"}]}}`, 537 js) 538 } 539 540 func TestFacetsFilterAndOrge2(t *testing.T) { 541 populateClusterWithFacets() 542 // find close or family friends of 1 after 2007-01-10 543 query := ` 544 { 545 me(func: uid(0x1)) { 546 name 547 friend @facets(eq(close, false) OR eq(family, true) AND ge(since, "2007-01-10")) { 548 name 549 uid 550 } 551 } 552 } 553 ` 554 555 js := processQueryNoErr(t, query) 556 require.JSONEq(t, 557 `{"data": {"me":[{"friend":[{"uid":"0x19","name":"Daryl Dixon"}],"name":"Michonne"}]}}`, 558 js) 559 } 560 561 func TestFacetsFilterNotAndOrgeMutuallyExclusive(t *testing.T) { 562 populateClusterWithFacets() 563 // find Not (close or family friends of 1 after 2007-01-10) 564 // Mutually exclusive of above result : TestFacetsFilterNotAndOrge 565 query := ` 566 { 567 me(func: uid(0x1)) { 568 name 569 friend @facets(not (eq(close, false) OR eq(family, true) AND ge(since, "2007-01-10"))) { 570 name 571 uid 572 } 573 } 574 } 575 ` 576 577 js := processQueryNoErr(t, query) 578 require.JSONEq(t, 579 `{"data": {"me":[{"friend":[{"uid":"0x17","name":"Rick Grimes"},{"uid":"0x18","name":"Glenn Rhee"},{"uid":"0x1f","name":"Andrea"},{"uid":"0x65"}],"name":"Michonne"}]}}`, 580 js) 581 } 582 583 func TestFacetsFilterUnknownFacets(t *testing.T) { 584 populateClusterWithFacets() 585 // unknown facets should filter out edges. 586 query := ` 587 { 588 me(func: uid(0x1)) { 589 name 590 friend @facets(ge(dob, "2007-01-10")) { 591 name 592 uid 593 } 594 } 595 } 596 ` 597 598 js := processQueryNoErr(t, query) 599 require.JSONEq(t, 600 `{"data": {"me":[{"name":"Michonne"}]}}`, 601 js) 602 } 603 604 func TestFacetsFilterUnknownOrKnown(t *testing.T) { 605 populateClusterWithFacets() 606 // unknown filters with OR do not have any effect on results 607 query := ` 608 { 609 me(func: uid(0x1)) { 610 name 611 friend @facets(ge(dob, "2007-01-10") OR eq(family, true)) { 612 name 613 uid 614 } 615 } 616 } 617 ` 618 619 js := processQueryNoErr(t, query) 620 require.JSONEq(t, 621 `{"data": {"me":[{"friend":[{"uid":"0x18","name":"Glenn Rhee"},{"uid":"0x19","name":"Daryl Dixon"}],"name":"Michonne"}]}}`, 622 js) 623 } 624 625 func TestFacetsFilterallofterms(t *testing.T) { 626 populateClusterWithFacets() 627 query := ` 628 { 629 me(func: uid(31)) { 630 name 631 friend @facets(allofterms(games, "football chess tennis")) { 632 name 633 uid 634 } 635 } 636 } 637 ` 638 639 js := processQueryNoErr(t, query) 640 require.JSONEq(t, 641 `{"data": {"me":[{"friend":[{"name":"Michonne","uid":"0x1"}],"name":"Andrea"}]}}`, 642 js) 643 } 644 645 func TestFacetsFilterAllofMultiple(t *testing.T) { 646 populateClusterWithFacets() 647 query := ` 648 { 649 me(func: uid(31)) { 650 name 651 friend @facets(allofterms(games, "football basketball")) { 652 name 653 uid 654 } 655 } 656 } 657 ` 658 659 js := processQueryNoErr(t, query) 660 require.JSONEq(t, 661 `{"data": {"me":[{"friend":[{"name":"Michonne","uid":"0x1"}, {"name":"Daryl Dixon","uid":"0x19"}],"name":"Andrea"}]}}`, 662 js) 663 } 664 665 func TestFacetsFilterAllofNone(t *testing.T) { 666 populateClusterWithFacets() 667 // nothing matches in allofterms 668 query := ` 669 { 670 me(func: uid(31)) { 671 name 672 friend @facets(allofterms(games, "football chess tennis cricket")) { 673 name 674 uid 675 } 676 } 677 } 678 ` 679 680 js := processQueryNoErr(t, query) 681 require.JSONEq(t, 682 `{"data": {"me":[{"name":"Andrea"}]}}`, 683 js) 684 } 685 686 func TestFacetsFilteranyofterms(t *testing.T) { 687 populateClusterWithFacets() 688 query := ` 689 { 690 me(func: uid(31)) { 691 name 692 friend @facets(anyofterms(games, "tennis cricket")) { 693 name 694 uid 695 } 696 } 697 } 698 ` 699 700 js := processQueryNoErr(t, query) 701 require.JSONEq(t, 702 `{"data": {"me":[{"friend":[{"uid":"0x1","name":"Michonne"}],"name":"Andrea"}]}}`, 703 js) 704 } 705 706 func TestFacetsFilterAnyofNone(t *testing.T) { 707 populateClusterWithFacets() 708 query := ` 709 { 710 me(func: uid(31)) { 711 name 712 friend @facets(anyofterms(games, "cricket")) { 713 name 714 uid 715 } 716 } 717 } 718 ` 719 720 js := processQueryNoErr(t, query) 721 require.JSONEq(t, 722 `{"data": {"me":[{"name":"Andrea"}]}}`, 723 js) 724 } 725 726 func TestFacetsFilterAllofanyofterms(t *testing.T) { 727 populateClusterWithFacets() 728 query := ` 729 { 730 me(func: uid(31)) { 731 name 732 friend @facets(allofterms(games, "basketball hockey") OR anyofterms(games, "chess")) { 733 name 734 uid 735 } 736 } 737 } 738 ` 739 740 js := processQueryNoErr(t, query) 741 require.JSONEq(t, 742 `{"data": {"me":[{"friend":[{"uid":"0x1","name":"Michonne"},{"uid":"0x19","name":"Daryl Dixon"}],"name":"Andrea"}]}}`, 743 js) 744 } 745 746 func TestFacetsFilterAllofAndanyofterms(t *testing.T) { 747 populateClusterWithFacets() 748 query := ` 749 { 750 me(func: uid(31)) { 751 name 752 friend @facets(allofterms(games, "hockey") AND anyofterms(games, "football basketball")) { 753 name 754 uid 755 } 756 } 757 } 758 ` 759 760 js := processQueryNoErr(t, query) 761 require.JSONEq(t, 762 `{"data": {"me":[{"friend":[{"uid":"0x19","name":"Daryl Dixon"}],"name":"Andrea"}]}}`, 763 js) 764 } 765 766 func TestFacetsFilterAtValueFail(t *testing.T) { 767 populateClusterWithFacets() 768 // facet filtering is not supported at value level. 769 query := ` 770 { 771 me(func: uid(1)) { 772 friend { 773 name @facets(eq(origin, "french")) 774 } 775 } 776 } 777 ` 778 779 _, err := processQuery(context.Background(), t, query) 780 require.Error(t, err) 781 } 782 783 func TestFacetsFilterAndRetrieval(t *testing.T) { 784 populateClusterWithFacets() 785 // Close should not be retrieved.. only used for filtering. 786 query := ` 787 { 788 me(func: uid(1)) { 789 name 790 friend @facets(eq(close, true)) @facets(family) { 791 name 792 uid 793 } 794 } 795 } 796 ` 797 798 js := processQueryNoErr(t, query) 799 require.JSONEq(t, 800 `{"data":{"me":[{"name":"Michonne","friend":[{"name":"Glenn Rhee","uid":"0x18","friend|family":true},{"uid":"0x65","friend|family":false}]}]}}`, 801 js) 802 } 803 804 func TestFacetWithLang(t *testing.T) { 805 populateClusterWithFacets() 806 query := ` 807 { 808 me(func: uid(320)) { 809 name@en @facets 810 } 811 } 812 ` 813 814 js := processQueryNoErr(t, query) 815 require.JSONEq(t, `{"data":{"me":[{"name@en|type":"Test facet with lang","name@en":"Test facet"}]}}`, js) 816 } 817 818 func TestFilterUidFacetMismatch(t *testing.T) { 819 populateClusterWithFacets() 820 query := ` 821 { 822 me(func: uid(0x1)) { 823 friend @filter(uid(24, 101)) @facets { 824 name 825 } 826 } 827 } 828 ` 829 js := processQueryNoErr(t, query) 830 require.JSONEq(t, `{"data":{"me":[{"friend":[{"name":"Glenn Rhee","friend|close":true,"friend|family":true,"friend|since":"2004-05-02T15:04:05Z","friend|tag":"Domain3"},{"friend|age":33,"friend|close":true,"friend|family":false,"friend|since":"2005-05-02T15:04:05Z"}]}]}}`, js) 831 } 832 833 func TestRecurseFacetOrder(t *testing.T) { 834 populateClusterWithFacets() 835 query := ` 836 { 837 me(func: uid(1)) @recurse(depth: 2) { 838 friend @facets(orderdesc: since) 839 uid 840 name 841 } 842 } 843 ` 844 js := processQueryNoErr(t, query) 845 require.JSONEq(t, `{"data":{"me":[{"friend":[ 846 {"uid":"0x19","name":"Daryl Dixon","friend|since":"2007-05-02T15:04:05Z"}, 847 {"uid":"0x17","name":"Rick Grimes","friend|since":"2006-01-02T15:04:05Z"}, 848 {"uid":"0x1f","name":"Andrea","friend|since":"2006-01-02T15:04:05Z"}, 849 {"uid":"0x65","friend|since":"2005-05-02T15:04:05Z"}, 850 {"uid":"0x18","name":"Glenn Rhee","friend|since":"2004-05-02T15:04:05Z"}], 851 "uid":"0x1","name":"Michonne"}]}}`, js) 852 853 query = ` 854 { 855 me(func: uid(1)) @recurse(depth: 2) { 856 friend @facets(orderasc: since) 857 uid 858 name 859 } 860 } 861 ` 862 js = processQueryNoErr(t, query) 863 require.JSONEq(t, `{"data":{"me":[{"friend":[ 864 {"uid":"0x18","name":"Glenn Rhee","friend|since":"2004-05-02T15:04:05Z"}, 865 {"uid":"0x65","friend|since":"2005-05-02T15:04:05Z"}, 866 {"uid":"0x17","name":"Rick Grimes","friend|since":"2006-01-02T15:04:05Z"}, 867 {"uid":"0x1f","name":"Andrea","friend|since":"2006-01-02T15:04:05Z"}, 868 {"uid":"0x19","name":"Daryl Dixon","friend|since":"2007-05-02T15:04:05Z"}], 869 "uid":"0x1","name":"Michonne"}]}}`, js) 870 } 871 872 func TestFacetsAlias(t *testing.T) { 873 populateClusterWithFacets() 874 query := ` 875 { 876 me(func: uid(0x1)) { 877 name @facets(o: origin) 878 friend @facets(family, tagalias: tag, since) { 879 name @facets(o: origin) 880 } 881 } 882 } 883 ` 884 885 js := processQueryNoErr(t, query) 886 require.Equal(t, `{"data":{"me":[{"o":"french","name":"Michonne","friend":[{"o":"french","name":"Rick Grimes","friend|since":"2006-01-02T15:04:05Z"},{"o":"french","name":"Glenn Rhee","friend|family":true,"friend|since":"2004-05-02T15:04:05Z","tagalias":"Domain3"},{"name":"Daryl Dixon","friend|family":true,"friend|since":"2007-05-02T15:04:05Z","tagalias":34},{"name":"Andrea","friend|since":"2006-01-02T15:04:05Z"},{"friend|family":false,"friend|since":"2005-05-02T15:04:05Z"}]}]}}`, js) 887 } 888 889 func TestFacetsAlias2(t *testing.T) { 890 populateClusterWithFacets() 891 query := ` 892 { 893 me2(func: uid(0x1)) { 894 friend @facets(f: family, a as since, orderdesc: tag, close) 895 } 896 897 me(func: uid(23)) { 898 name 899 val(a) 900 } 901 } 902 ` 903 904 js := processQueryNoErr(t, query) 905 require.JSONEq(t, `{"data":{"me2":[{"friend":[{"friend|close":true,"f":false,"friend|since":"2005-05-02T15:04:05Z"},{"friend|since":"2006-01-02T15:04:05Z"},{"friend|since":"2006-01-02T15:04:05Z"},{"friend|close":true,"f":true,"friend|since":"2004-05-02T15:04:05Z","friend|tag":"Domain3"},{"friend|close":false,"f":true,"friend|since":"2007-05-02T15:04:05Z","friend|tag":34}]}],"me":[{"name":"Rick Grimes", "val(a)":"2006-01-02T15:04:05Z"}]}}`, js) 906 } 907 908 func TestTypeExpandFacets(t *testing.T) { 909 query := `{ 910 q(func: eq(make, "Toyota")) { 911 expand(_all_) { 912 uid 913 } 914 } 915 }` 916 js := processQueryNoErr(t, query) 917 require.JSONEq(t, `{"data": {"q":[ 918 {"make":"Toyota","model":"Prius", "model@jp":"プリウス", "model|type":"Electric", 919 "year":2009}]}}`, js) 920 }