Spaces:
Running
Running
// _ _ | |
// __ _____ __ ___ ___ __ _| |_ ___ | |
// \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ | |
// \ V V / __/ (_| |\ V /| | (_| | || __/ | |
// \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| | |
// | |
// Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. | |
// | |
// CONTACT: [email protected] | |
// | |
package test | |
import ( | |
"strings" | |
"testing" | |
graphqlhelper "github.com/weaviate/weaviate/test/helper/graphql" | |
"github.com/stretchr/testify/assert" | |
"github.com/stretchr/testify/require" | |
"github.com/weaviate/weaviate/test/helper" | |
) | |
func gettingObjectsWithGrouping(t *testing.T) { | |
t.Run("without grouping <- this is the control", func(t *testing.T) { | |
query := ` | |
{ | |
Get { | |
Company { | |
name | |
} | |
} | |
} | |
` | |
result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) | |
companies := result.Get("Get", "Company").AsSlice() | |
expected := []interface{}{ | |
map[string]interface{}{"name": "Microsoft Inc."}, | |
map[string]interface{}{"name": "Microsoft Incorporated"}, | |
map[string]interface{}{"name": "Microsoft"}, | |
map[string]interface{}{"name": "Apple Inc."}, | |
map[string]interface{}{"name": "Apple Incorporated"}, | |
map[string]interface{}{"name": "Apple"}, | |
map[string]interface{}{"name": "Google Inc."}, | |
map[string]interface{}{"name": "Google Incorporated"}, | |
map[string]interface{}{"name": "Google"}, | |
} | |
assert.ElementsMatch(t, expected, companies) | |
}) | |
t.Run("grouping mode set to merge and force to 1.0", func(t *testing.T) { | |
query := ` | |
{ | |
Get { | |
Company(group: {type: merge, force:1.0}) { | |
name | |
inCity { | |
... on City {name} | |
} | |
} | |
} | |
} | |
` | |
result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) | |
companies := result.Get("Get", "Company").AsSlice() | |
require.Len(t, companies, 1) | |
companyNames := companies[0].(map[string]interface{})["name"].(string) | |
assert.NotEmpty(t, companies) | |
mustContain := []string{"Apple", "Google", "Microsoft"} | |
for _, companyName := range mustContain { | |
if !strings.Contains(companyNames, companyName) { | |
t.Errorf("%s not contained in %v", companyName, companyNames) | |
} | |
} | |
companyCities := companies[0].(map[string]interface{})["inCity"].([]interface{}) | |
expectedCities := []map[string]interface{}{ | |
{"name": "Dusseldorf"}, | |
{"name": "Amsterdam"}, | |
{"name": "Berlin"}, | |
} | |
assert.ElementsMatch(t, expectedCities, companyCities) | |
}) | |
t.Run("grouping mode set to merge and force to 0.0", func(t *testing.T) { | |
query := ` | |
{ | |
Get { | |
Company(group: {type: merge, force:0.0}) { | |
name | |
inCity { | |
... on City { | |
name | |
} | |
} | |
} | |
} | |
} | |
` | |
result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) | |
companies := result.Get("Get", "Company").AsSlice() | |
require.Len(t, companies, 9) | |
getName := func(value map[string]interface{}) string { | |
return value["name"].(string) | |
} | |
getCities := func(value map[string]interface{}) []string { | |
inCity := value["inCity"].([]interface{}) | |
cities := make([]string, len(inCity)) | |
for i := range inCity { | |
cityVal := inCity[i].(map[string]interface{}) | |
cities[i] = getName(cityVal) | |
} | |
return cities | |
} | |
for _, current := range companies { | |
currentMap := current.(map[string]interface{}) | |
if getName(currentMap) == "Microsoft Incorporated" { | |
assert.Len(t, getCities(currentMap), 2) | |
} | |
if getName(currentMap) == "Microsoft Inc." { | |
assert.Len(t, getCities(currentMap), 1) | |
} | |
if getName(currentMap) == "Microsoft" { | |
assert.Len(t, getCities(currentMap), 1) | |
} | |
} | |
}) | |
t.Run("grouping mode set to closest and force to 0.1", func(t *testing.T) { | |
query := ` | |
{ | |
Get { | |
Company(group: {type: closest, force:0.1}) { | |
name | |
inCity { | |
... on City { | |
name | |
} | |
} | |
} | |
} | |
} | |
` | |
result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) | |
companies := result.Get("Get", "Company").AsSlice() | |
assert.True(t, len(companies) > 0) | |
}) | |
t.Run("grouping mode set to closest with near text", func(t *testing.T) { | |
query := ` | |
{ | |
Get { | |
Company(nearText: {concepts: "Apple"}, group: {type: closest, force:1.0}) { | |
name | |
} | |
} | |
} | |
` | |
result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) | |
companies := result.Get("Get", "Company").AsSlice() | |
assert.True(t, len(companies) == 1) | |
}) | |
t.Run("grouping with where filter", func(t *testing.T) { | |
query := ` | |
{ | |
Get { | |
Company(group:{type:merge force:1.0} where:{path:["id"] operator:Like valueText:"*"}) { | |
name | |
inCity { | |
... on City { | |
name | |
} | |
} | |
} | |
} | |
} | |
` | |
result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) | |
grouped := result.Get("Get", "Company").AsSlice() | |
require.Len(t, grouped, 1) | |
groupedName := grouped[0].(map[string]interface{})["name"].(string) | |
assert.Equal(t, "Microsoft Inc. (Microsoft Incorporated, Microsoft, Apple Inc., "+ | |
"Apple Incorporated, Apple, Google Inc., Google Incorporated, Google)", | |
groupedName) | |
companyCities := grouped[0].(map[string]interface{})["inCity"].([]interface{}) | |
expectedCities := []map[string]interface{}{ | |
{"name": "Dusseldorf"}, | |
{"name": "Amsterdam"}, | |
{"name": "Berlin"}, | |
} | |
assert.ElementsMatch(t, expectedCities, companyCities) | |
// this query should yield the same results as the above, as the above where filter will | |
// match all records. checking the previous payload with the one below is a sanity check | |
// for the sake of validating the fix for [github issue 1958] | |
// (https://github.com/weaviate/weaviate/issues/1958) | |
// UPDATE: due to introducing roaring bitmaps as set holding docIDs of filtered documents | |
// internal order of results returned has changed from property value based to docID based, | |
// but set content remain unchanged | |
// for that reason grouped name in the following test is different with and without filters, | |
// though it still contains the same elements | |
queryWithoutWhere := ` | |
{ | |
Get { | |
Company(group:{type:merge force:1.0}) { | |
name | |
inCity { | |
... on City { | |
name | |
} | |
} | |
} | |
} | |
} | |
` | |
result = graphqlhelper.AssertGraphQL(t, helper.RootAuth, queryWithoutWhere) | |
groupedWithoutWhere := result.Get("Get", "Company").AsSlice() | |
groupedWithoutWhereName := groupedWithoutWhere[0].(map[string]interface{})["name"].(string) | |
assert.Equal(t, "Apple Inc. (Google Incorporated, Google Inc., Microsoft Incorporated, "+ | |
"Apple, Apple Incorporated, Google, Microsoft Inc., Microsoft)", | |
groupedWithoutWhereName) | |
companyCities = groupedWithoutWhere[0].(map[string]interface{})["inCity"].([]interface{}) | |
assert.ElementsMatch(t, expectedCities, companyCities) | |
}) | |
t.Run("grouping with sort", func(t *testing.T) { | |
query := ` | |
{ | |
Get { | |
Company(group:{type:merge force:1.0} sort:{path:["name"]}) { | |
name | |
inCity { | |
... on City { | |
name | |
} | |
} | |
} | |
} | |
} | |
` | |
result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) | |
grouped := result.Get("Get", "Company").AsSlice() | |
require.Len(t, grouped, 1) | |
groupedName := grouped[0].(map[string]interface{})["name"].(string) | |
assert.Equal(t, "Apple (Apple Inc., Apple Incorporated, Google, Google Inc., "+ | |
"Google Incorporated, Microsoft, Microsoft Inc., Microsoft Incorporated)", | |
groupedName) | |
groupedCities := grouped[0].(map[string]interface{})["inCity"].([]interface{}) | |
expectedCities := []map[string]interface{}{ | |
{"name": "Dusseldorf"}, | |
{"name": "Amsterdam"}, | |
{"name": "Berlin"}, | |
} | |
assert.ElementsMatch(t, expectedCities, groupedCities) | |
}) | |
// temporarily removed due to | |
// https://github.com/weaviate/weaviate/issues/1302 | |
// t.Run("grouping mode set to closest", func(t *testing.T) { | |
// query := ` | |
// { | |
// Get { | |
// Company(group: {type: closest, force:0.10}) { | |
// name | |
// } | |
// } | |
// } | |
// ` | |
// result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) | |
// companies := result.Get("Get", "Company").AsSlice() | |
// assert.Len(t, companies, 3) | |
// mustContain := []string{"Apple", "Microsoft", "Google"} | |
// outer: | |
// for _, toContain := range mustContain { | |
// for _, current := range companies { | |
// if strings.Contains(current.(map[string]interface{})["name"].(string), toContain) { | |
// continue outer | |
// } | |
// } | |
// t.Errorf("%s not contained in %v", toContain, companies) | |
// } | |
// }) | |
// ignore as 0.16.0 contextionaries aren't compatible with this test | |
// t.Run("grouping mode set to merge", func(t *testing.T) { | |
// query := ` | |
// { | |
// Get { | |
// Company(group: {type: merge, force:0.1}) { | |
// name | |
// inCity { | |
// ... on City { | |
// name | |
// } | |
// } | |
// } | |
// } | |
// } | |
// ` | |
// result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) | |
// companies := result.Get("Get", "Company").AsSlice() | |
// assert.Len(t, companies, 3) | |
// mustContain := [][]string{ | |
// []string{"Apple", "Apple Inc.", "Apple Incorporated"}, | |
// []string{"Microsoft", "Microsoft Inc.", "Microsoft Incorporated"}, | |
// []string{"Google", "Google Inc.", "Google Incorporated"}, | |
// } | |
// allContained := func(current map[string]interface{}, toContains []string) bool { | |
// for _, toContain := range toContains { | |
// if !strings.Contains(current["name"].(string), toContain) { | |
// return false | |
// } | |
// } | |
// return true | |
// } | |
// outer: | |
// for _, toContain := range mustContain { | |
// for _, current := range companies { | |
// if allContained(current.(map[string]interface{}), toContain) { | |
// continue outer | |
// } | |
// } | |
// t.Errorf("%s not contained in %v", toContain, companies) | |
// } | |
// }) | |
} | |