github.com/weaviate/weaviate@v1.24.6/test/acceptance/graphql_resolvers/local_get_with_grouping_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 "strings" 16 "testing" 17 18 graphqlhelper "github.com/weaviate/weaviate/test/helper/graphql" 19 20 "github.com/stretchr/testify/assert" 21 "github.com/stretchr/testify/require" 22 "github.com/weaviate/weaviate/test/helper" 23 ) 24 25 func gettingObjectsWithGrouping(t *testing.T) { 26 t.Run("without grouping <- this is the control", func(t *testing.T) { 27 query := ` 28 { 29 Get { 30 Company { 31 name 32 } 33 } 34 } 35 ` 36 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) 37 companies := result.Get("Get", "Company").AsSlice() 38 39 expected := []interface{}{ 40 map[string]interface{}{"name": "Microsoft Inc."}, 41 map[string]interface{}{"name": "Microsoft Incorporated"}, 42 map[string]interface{}{"name": "Microsoft"}, 43 map[string]interface{}{"name": "Apple Inc."}, 44 map[string]interface{}{"name": "Apple Incorporated"}, 45 map[string]interface{}{"name": "Apple"}, 46 map[string]interface{}{"name": "Google Inc."}, 47 map[string]interface{}{"name": "Google Incorporated"}, 48 map[string]interface{}{"name": "Google"}, 49 } 50 51 assert.ElementsMatch(t, expected, companies) 52 }) 53 54 t.Run("grouping mode set to merge and force to 1.0", func(t *testing.T) { 55 query := ` 56 { 57 Get { 58 Company(group: {type: merge, force:1.0}) { 59 name 60 inCity { 61 ... on City {name} 62 } 63 } 64 } 65 } 66 ` 67 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) 68 companies := result.Get("Get", "Company").AsSlice() 69 70 require.Len(t, companies, 1) 71 72 companyNames := companies[0].(map[string]interface{})["name"].(string) 73 assert.NotEmpty(t, companies) 74 75 mustContain := []string{"Apple", "Google", "Microsoft"} 76 for _, companyName := range mustContain { 77 if !strings.Contains(companyNames, companyName) { 78 t.Errorf("%s not contained in %v", companyName, companyNames) 79 } 80 } 81 82 companyCities := companies[0].(map[string]interface{})["inCity"].([]interface{}) 83 expectedCities := []map[string]interface{}{ 84 {"name": "Dusseldorf"}, 85 {"name": "Amsterdam"}, 86 {"name": "Berlin"}, 87 } 88 89 assert.ElementsMatch(t, expectedCities, companyCities) 90 }) 91 92 t.Run("grouping mode set to merge and force to 0.0", func(t *testing.T) { 93 query := ` 94 { 95 Get { 96 Company(group: {type: merge, force:0.0}) { 97 name 98 inCity { 99 ... on City { 100 name 101 } 102 } 103 } 104 } 105 } 106 ` 107 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) 108 companies := result.Get("Get", "Company").AsSlice() 109 110 require.Len(t, companies, 9) 111 112 getName := func(value map[string]interface{}) string { 113 return value["name"].(string) 114 } 115 116 getCities := func(value map[string]interface{}) []string { 117 inCity := value["inCity"].([]interface{}) 118 cities := make([]string, len(inCity)) 119 for i := range inCity { 120 cityVal := inCity[i].(map[string]interface{}) 121 cities[i] = getName(cityVal) 122 } 123 return cities 124 } 125 126 for _, current := range companies { 127 currentMap := current.(map[string]interface{}) 128 if getName(currentMap) == "Microsoft Incorporated" { 129 assert.Len(t, getCities(currentMap), 2) 130 } 131 if getName(currentMap) == "Microsoft Inc." { 132 assert.Len(t, getCities(currentMap), 1) 133 } 134 if getName(currentMap) == "Microsoft" { 135 assert.Len(t, getCities(currentMap), 1) 136 } 137 } 138 }) 139 140 t.Run("grouping mode set to closest and force to 0.1", func(t *testing.T) { 141 query := ` 142 { 143 Get { 144 Company(group: {type: closest, force:0.1}) { 145 name 146 inCity { 147 ... on City { 148 name 149 } 150 } 151 } 152 } 153 } 154 ` 155 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) 156 companies := result.Get("Get", "Company").AsSlice() 157 158 assert.True(t, len(companies) > 0) 159 }) 160 161 t.Run("grouping mode set to closest with near text", func(t *testing.T) { 162 query := ` 163 { 164 Get { 165 Company(nearText: {concepts: "Apple"}, group: {type: closest, force:1.0}) { 166 name 167 } 168 } 169 } 170 ` 171 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) 172 companies := result.Get("Get", "Company").AsSlice() 173 174 assert.True(t, len(companies) == 1) 175 }) 176 177 t.Run("grouping with where filter", func(t *testing.T) { 178 query := ` 179 { 180 Get { 181 Company(group:{type:merge force:1.0} where:{path:["id"] operator:Like valueText:"*"}) { 182 name 183 inCity { 184 ... on City { 185 name 186 } 187 } 188 } 189 } 190 } 191 ` 192 193 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) 194 grouped := result.Get("Get", "Company").AsSlice() 195 require.Len(t, grouped, 1) 196 groupedName := grouped[0].(map[string]interface{})["name"].(string) 197 assert.Equal(t, "Microsoft Inc. (Microsoft Incorporated, Microsoft, Apple Inc., "+ 198 "Apple Incorporated, Apple, Google Inc., Google Incorporated, Google)", 199 groupedName) 200 201 companyCities := grouped[0].(map[string]interface{})["inCity"].([]interface{}) 202 expectedCities := []map[string]interface{}{ 203 {"name": "Dusseldorf"}, 204 {"name": "Amsterdam"}, 205 {"name": "Berlin"}, 206 } 207 208 assert.ElementsMatch(t, expectedCities, companyCities) 209 210 // this query should yield the same results as the above, as the above where filter will 211 // match all records. checking the previous payload with the one below is a sanity check 212 // for the sake of validating the fix for [github issue 1958] 213 // (https://github.com/weaviate/weaviate/issues/1958) 214 // UPDATE: due to introducing roaring bitmaps as set holding docIDs of filtered documents 215 // internal order of results returned has changed from property value based to docID based, 216 // but set content remain unchanged 217 // for that reason grouped name in the following test is different with and without filters, 218 // though it still contains the same elements 219 queryWithoutWhere := ` 220 { 221 Get { 222 Company(group:{type:merge force:1.0}) { 223 name 224 inCity { 225 ... on City { 226 name 227 } 228 } 229 } 230 } 231 } 232 ` 233 result = graphqlhelper.AssertGraphQL(t, helper.RootAuth, queryWithoutWhere) 234 groupedWithoutWhere := result.Get("Get", "Company").AsSlice() 235 groupedWithoutWhereName := groupedWithoutWhere[0].(map[string]interface{})["name"].(string) 236 assert.Equal(t, "Apple Inc. (Google Incorporated, Google Inc., Microsoft Incorporated, "+ 237 "Apple, Apple Incorporated, Google, Microsoft Inc., Microsoft)", 238 groupedWithoutWhereName) 239 240 companyCities = groupedWithoutWhere[0].(map[string]interface{})["inCity"].([]interface{}) 241 assert.ElementsMatch(t, expectedCities, companyCities) 242 }) 243 244 t.Run("grouping with sort", func(t *testing.T) { 245 query := ` 246 { 247 Get { 248 Company(group:{type:merge force:1.0} sort:{path:["name"]}) { 249 name 250 inCity { 251 ... on City { 252 name 253 } 254 } 255 } 256 } 257 } 258 ` 259 260 result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) 261 grouped := result.Get("Get", "Company").AsSlice() 262 require.Len(t, grouped, 1) 263 groupedName := grouped[0].(map[string]interface{})["name"].(string) 264 assert.Equal(t, "Apple (Apple Inc., Apple Incorporated, Google, Google Inc., "+ 265 "Google Incorporated, Microsoft, Microsoft Inc., Microsoft Incorporated)", 266 groupedName) 267 268 groupedCities := grouped[0].(map[string]interface{})["inCity"].([]interface{}) 269 expectedCities := []map[string]interface{}{ 270 {"name": "Dusseldorf"}, 271 {"name": "Amsterdam"}, 272 {"name": "Berlin"}, 273 } 274 275 assert.ElementsMatch(t, expectedCities, groupedCities) 276 }) 277 278 // temporarily removed due to 279 // https://github.com/weaviate/weaviate/issues/1302 280 // t.Run("grouping mode set to closest", func(t *testing.T) { 281 // query := ` 282 // { 283 // Get { 284 // Company(group: {type: closest, force:0.10}) { 285 // name 286 // } 287 // } 288 // } 289 // ` 290 // result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) 291 // companies := result.Get("Get", "Company").AsSlice() 292 293 // assert.Len(t, companies, 3) 294 // mustContain := []string{"Apple", "Microsoft", "Google"} 295 // outer: 296 // for _, toContain := range mustContain { 297 // for _, current := range companies { 298 // if strings.Contains(current.(map[string]interface{})["name"].(string), toContain) { 299 // continue outer 300 // } 301 // } 302 303 // t.Errorf("%s not contained in %v", toContain, companies) 304 // } 305 // }) 306 307 // ignore as 0.16.0 contextionaries aren't compatible with this test 308 // t.Run("grouping mode set to merge", func(t *testing.T) { 309 // query := ` 310 // { 311 // Get { 312 // Company(group: {type: merge, force:0.1}) { 313 // name 314 // inCity { 315 // ... on City { 316 // name 317 // } 318 // } 319 // } 320 // } 321 // } 322 // ` 323 // result := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) 324 // companies := result.Get("Get", "Company").AsSlice() 325 326 // assert.Len(t, companies, 3) 327 // mustContain := [][]string{ 328 // []string{"Apple", "Apple Inc.", "Apple Incorporated"}, 329 // []string{"Microsoft", "Microsoft Inc.", "Microsoft Incorporated"}, 330 // []string{"Google", "Google Inc.", "Google Incorporated"}, 331 // } 332 333 // allContained := func(current map[string]interface{}, toContains []string) bool { 334 // for _, toContain := range toContains { 335 // if !strings.Contains(current["name"].(string), toContain) { 336 // return false 337 // } 338 // } 339 // return true 340 // } 341 342 // outer: 343 // for _, toContain := range mustContain { 344 // for _, current := range companies { 345 // if allContained(current.(map[string]interface{}), toContain) { 346 // continue outer 347 // } 348 // } 349 350 // t.Errorf("%s not contained in %v", toContain, companies) 351 // } 352 // }) 353 }