github.com/unigraph-dev/dgraph@v1.1.1-0.20200923154953-8b52b426f765/query/query4_test.go (about) 1 /* 2 * Copyright 2019 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 // "encoding/json" 22 // "fmt" 23 // "strings" 24 "testing" 25 26 "github.com/stretchr/testify/require" 27 // "google.golang.org/grpc/metadata" 28 ) 29 30 func TestDeleteAndReaddIndex(t *testing.T) { 31 // Add new predicate with several indices. 32 s1 := testSchema + "\n numerology: string @index(exact, term, fulltext) .\n" 33 setSchema(s1) 34 triples := ` 35 <0x666> <numerology> "This number is evil" . 36 <0x777> <numerology> "This number is good" . 37 ` 38 addTriplesToCluster(triples) 39 40 // Verify fulltext index works as expected. 41 q1 := ` 42 { 43 me(func: anyoftext(numerology, "numbers")) { 44 uid 45 numerology 46 } 47 }` 48 js := processQueryNoErr(t, q1) 49 require.JSONEq(t, `{"data": {"me": [ 50 {"uid": "0x666", "numerology": "This number is evil"}, 51 {"uid": "0x777", "numerology": "This number is good"} 52 ]}}`, js) 53 54 // Remove the fulltext index and verify the previous query is no longer supported. 55 s2 := testSchema + "\n numerology: string @index(exact, term) .\n" 56 setSchema(s2) 57 _, err := processQuery(context.Background(), t, q1) 58 require.Error(t, err) 59 require.Contains(t, err.Error(), "Attribute numerology is not indexed with type fulltext") 60 61 // Verify term index still works as expected. 62 q2 := ` 63 { 64 me(func: anyofterms(numerology, "number")) { 65 uid 66 numerology 67 } 68 }` 69 js = processQueryNoErr(t, q2) 70 require.JSONEq(t, `{"data": {"me": [ 71 {"uid": "0x666", "numerology": "This number is evil"}, 72 {"uid": "0x777", "numerology": "This number is good"} 73 ]}}`, js) 74 75 // Re-add index and verify that the original query works again. 76 setSchema(s1) 77 js = processQueryNoErr(t, q1) 78 require.JSONEq(t, `{"data": {"me": [ 79 {"uid": "0x666", "numerology": "This number is evil"}, 80 {"uid": "0x777", "numerology": "This number is good"} 81 ]}}`, js) 82 83 // Finally, drop the predicate and restore schema. 84 dropPredicate("numerology") 85 setSchema(testSchema) 86 } 87 88 func TestDeleteAndReaddCount(t *testing.T) { 89 // Add new predicate with count index. 90 s1 := testSchema + "\n numerology: string @count .\n" 91 setSchema(s1) 92 triples := ` 93 <0x666> <numerology> "This number is evil" . 94 <0x777> <numerology> "This number is good" . 95 ` 96 addTriplesToCluster(triples) 97 98 // Verify count index works as expected. 99 q1 := ` 100 { 101 me(func: gt(count(numerology), 0)) { 102 uid 103 numerology 104 } 105 }` 106 js := processQueryNoErr(t, q1) 107 require.JSONEq(t, `{"data": {"me": [ 108 {"uid": "0x666", "numerology": "This number is evil"}, 109 {"uid": "0x777", "numerology": "This number is good"} 110 ]}}`, js) 111 112 // Remove the count index and verify the previous query is no longer supported. 113 s2 := testSchema + "\n numerology: string .\n" 114 setSchema(s2) 115 _, err := processQuery(context.Background(), t, q1) 116 require.Error(t, err) 117 require.Contains(t, err.Error(), "Need @count directive in schema for attr: numerology") 118 119 // Re-add count index and verify that the original query works again. 120 setSchema(s1) 121 js = processQueryNoErr(t, q1) 122 require.JSONEq(t, `{"data": {"me": [ 123 {"uid": "0x666", "numerology": "This number is evil"}, 124 {"uid": "0x777", "numerology": "This number is good"} 125 ]}}`, js) 126 127 // Finally, drop the predicate and restore schema. 128 dropPredicate("numerology") 129 setSchema(testSchema) 130 } 131 132 func TestDeleteAndReaddReverse(t *testing.T) { 133 // Add new predicate with a reverse edge. 134 s1 := testSchema + "\n child_pred: uid @reverse .\n" 135 setSchema(s1) 136 triples := `<0x666> <child_pred> <0x777> .` 137 addTriplesToCluster(triples) 138 139 // Verify reverse edges works as expected. 140 q1 := ` 141 { 142 me(func: uid(0x777)) { 143 ~child_pred { 144 uid 145 } 146 } 147 }` 148 js := processQueryNoErr(t, q1) 149 require.JSONEq(t, `{"data": {"me": [{"~child_pred": [{"uid": "0x666"}]}]}}`, js) 150 151 // Remove the reverse edges and verify the previous query is no longer supported. 152 s2 := testSchema + "\n child_pred: uid .\n" 153 setSchema(s2) 154 _, err := processQuery(context.Background(), t, q1) 155 require.Error(t, err) 156 require.Contains(t, err.Error(), "Predicate child_pred doesn't have reverse edge") 157 158 // Re-add reverse edges and verify that the original query works again. 159 setSchema(s1) 160 js = processQueryNoErr(t, q1) 161 require.JSONEq(t, `{"data": {"me": [{"~child_pred": [{"uid": "0x666"}]}]}}`, js) 162 163 // Finally, drop the predicate and restore schema. 164 dropPredicate("child_pred") 165 setSchema(testSchema) 166 } 167 168 func TestDropPredicate(t *testing.T) { 169 // Add new predicate with several indices. 170 s1 := testSchema + "\n numerology: string @index(term) .\n" 171 setSchema(s1) 172 triples := ` 173 <0x666> <numerology> "This number is evil" . 174 <0x777> <numerology> "This number is good" . 175 ` 176 addTriplesToCluster(triples) 177 178 // Verify queries work as expected. 179 q1 := ` 180 { 181 me(func: anyofterms(numerology, "number")) { 182 uid 183 numerology 184 } 185 }` 186 js := processQueryNoErr(t, q1) 187 require.JSONEq(t, `{"data": {"me": [ 188 {"uid": "0x666", "numerology": "This number is evil"}, 189 {"uid": "0x777", "numerology": "This number is good"} 190 ]}}`, js) 191 192 // Finally, drop the predicate and verify the query no longer works because 193 // the index was dropped when all the data for that predicate was deleted. 194 dropPredicate("numerology") 195 _, err := processQuery(context.Background(), t, q1) 196 require.Error(t, err) 197 require.Contains(t, err.Error(), "Attribute numerology is not indexed with type term") 198 199 // Finally, restore the schema. 200 setSchema(testSchema) 201 } 202 203 func TestNestedExpandAll(t *testing.T) { 204 query := `{ 205 q(func: has(node)) { 206 uid 207 expand(_all_) { 208 uid 209 node { 210 uid 211 expand(_all_) 212 } 213 } 214 } 215 }` 216 js := processQueryNoErr(t, query) 217 require.JSONEq(t, `{"data": { 218 "q": [ 219 { 220 "uid": "0x2b5c", 221 "name": "expand", 222 "node": [ 223 { 224 "uid": "0x2b5c", 225 "node": [ 226 { 227 "uid": "0x2b5c", 228 "name": "expand" 229 } 230 ] 231 } 232 ] 233 } 234 ]}}`, js) 235 } 236 237 func TestNoResultsFilter(t *testing.T) { 238 query := `{ 239 q(func: has(nonexistent_pred)) @filter(le(name, "abc")) { 240 uid 241 } 242 }` 243 js := processQueryNoErr(t, query) 244 require.JSONEq(t, `{"data": {"q": []}}`, js) 245 } 246 247 func TestNoResultsPagination(t *testing.T) { 248 query := `{ 249 q(func: has(nonexistent_pred), first: 50) { 250 uid 251 } 252 }` 253 js := processQueryNoErr(t, query) 254 require.JSONEq(t, `{"data": {"q": []}}`, js) 255 } 256 257 func TestNoResultsGroupBy(t *testing.T) { 258 query := `{ 259 q(func: has(nonexistent_pred)) @groupby(name) { 260 count(uid) 261 } 262 }` 263 js := processQueryNoErr(t, query) 264 require.JSONEq(t, `{"data": {}}`, js) 265 } 266 267 func TestNoResultsOrder(t *testing.T) { 268 query := `{ 269 q(func: has(nonexistent_pred), orderasc: name) { 270 uid 271 } 272 }` 273 js := processQueryNoErr(t, query) 274 require.JSONEq(t, `{"data": {"q": []}}`, js) 275 } 276 277 func TestNoResultsCount(t *testing.T) { 278 query := `{ 279 q(func: has(nonexistent_pred)) { 280 uid 281 count(friend) 282 } 283 }` 284 js := processQueryNoErr(t, query) 285 require.JSONEq(t, `{"data": {"q": []}}`, js) 286 } 287 288 func TestTypeExpandAll(t *testing.T) { 289 query := `{ 290 q(func: eq(make, "Ford")) { 291 expand(_all_) { 292 uid 293 } 294 } 295 }` 296 js := processQueryNoErr(t, query) 297 require.JSONEq(t, `{"data": {"q":[ 298 {"make":"Ford","model":"Focus","year":2008, "~previous_model": [{"uid":"0xc9"}]}, 299 {"make":"Ford","model":"Focus","year":2009, "previous_model": {"uid":"0xc8"}} 300 ]}}`, js) 301 } 302 303 func TestTypeExpandForward(t *testing.T) { 304 query := `{ 305 q(func: eq(make, "Ford")) { 306 expand(_forward_) { 307 uid 308 } 309 } 310 }` 311 js := processQueryNoErr(t, query) 312 require.JSONEq(t, `{"data": {"q":[ 313 {"make":"Ford","model":"Focus","year":2008}, 314 {"make":"Ford","model":"Focus","year":2009, "previous_model": {"uid":"0xc8"}} 315 ]}}`, js) 316 } 317 318 func TestTypeExpandReverse(t *testing.T) { 319 query := `{ 320 q(func: eq(make, "Ford")) { 321 expand(_reverse_) { 322 uid 323 } 324 } 325 }` 326 js := processQueryNoErr(t, query) 327 require.JSONEq(t, `{"data": {"q":[ 328 {"~previous_model": [{"uid":"0xc9"}]} 329 ]}}`, js) 330 } 331 332 func TestTypeExpandLang(t *testing.T) { 333 query := `{ 334 q(func: eq(make, "Toyota")) { 335 expand(_all_) { 336 uid 337 } 338 } 339 }` 340 js := processQueryNoErr(t, query) 341 require.JSONEq(t, `{"data": {"q":[ 342 {"make":"Toyota","model":"Prius", "model@jp":"プリウス", "year":2009}]}}`, js) 343 }