@@ -377,11 +377,20 @@ func (qs *queryState) handleValuePostings(ctx context.Context, args funcArgs) er
377
377
outputs := make ([]* pb.Result , numGo )
378
378
listType := schema .State ().IsList (q .Attr )
379
379
380
+ // These are certain special cases where we can get away with reading only the latest value
381
+ // Lang doesn't work because we would be storing various different languages at various
382
+ // time. So when we go to read the latest value, we might get a different language.
383
+ // Similarly with DoCount and ExpandAll and Facets. List types are also not supported
384
+ // because list is stored by time, and we combine all the list items at various timestamps.
385
+ hasLang := schema .State ().HasLang (q .Attr )
386
+ getMultiplePosting := q .DoCount || q .ExpandAll || listType || hasLang || q .FacetParam != nil
387
+
380
388
calculate := func (start , end int ) error {
381
389
x .AssertTrue (start % width == 0 )
382
390
out := & pb.Result {}
383
391
outputs [start / width ] = out
384
392
393
+ cache := make ([]* pb.PostingList , 0 )
385
394
for i := start ; i < end ; i ++ {
386
395
select {
387
396
case <- ctx .Done ():
@@ -391,49 +400,86 @@ func (qs *queryState) handleValuePostings(ctx context.Context, args funcArgs) er
391
400
key := x .DataKey (q .Attr , q .UidList .Uids [i ])
392
401
393
402
// Get or create the posting list for an entity, attribute combination.
394
- pl , err := qs .cache .Get (key )
395
- if err != nil {
396
- return err
397
- }
398
403
399
- // If count is being requested, there is no need to populate value and facets matrix.
400
- if q .DoCount {
401
- count , err := countForValuePostings (args , pl , facetsTree , listType )
402
- if err != nil && err != posting .ErrNoValue {
404
+ var vals []types.Val
405
+ fcs := & pb.FacetsList {FacetsList : make ([]* pb.Facets , 0 )} // TODO Figure out how it is stored
406
+
407
+ if ! getMultiplePosting {
408
+ if len (cache ) == 0 {
409
+ keys := make ([][]byte , 10 )
410
+ keys [0 ] = key
411
+ for j := i + 1 ; j < i + 10 && j < end ; j ++ {
412
+ keys [j - i ] = x .DataKey (q .Attr , q .UidList .Uids [j ])
413
+ }
414
+ cache , err = qs .cache .GetBatchSinglePosting (keys )
415
+ if err != nil {
416
+ return err
417
+ }
418
+ }
419
+ pl := cache [0 ]
420
+ if len (cache ) > 1 {
421
+ cache = cache [1 :]
422
+ }
423
+ if pl == nil || len (pl .Postings ) == 0 {
424
+ out .UidMatrix = append (out .UidMatrix , & pb.List {})
425
+ out .FacetMatrix = append (out .FacetMatrix , & pb.FacetsList {})
426
+ out .ValueMatrix = append (out .ValueMatrix ,
427
+ & pb.ValueList {Values : []* pb.TaskValue {}})
428
+ continue
429
+ }
430
+ vals = make ([]types.Val , len (pl .Postings ))
431
+ for i , p := range pl .Postings {
432
+ vals [i ] = types.Val {
433
+ Tid : types .TypeID (p .ValType ),
434
+ Value : p .Value ,
435
+ }
436
+ }
437
+ } else {
438
+ pl , err := qs .cache .Get (key )
439
+ if err != nil {
403
440
return err
404
441
}
405
- out .Counts = append (out .Counts , uint32 (count ))
406
- // Add an empty UID list to make later processing consistent.
407
- out .UidMatrix = append (out .UidMatrix , & pb.List {})
408
- continue
409
- }
410
442
411
- vals , fcs , err := retrieveValuesAndFacets (args , pl , facetsTree , listType )
412
- switch {
413
- case err == posting .ErrNoValue || (err == nil && len (vals ) == 0 ):
414
- // This branch is taken when the value does not exist in the pl or
415
- // the number of values retrieved is zero (there could still be facets).
416
- // We add empty lists to the UidMatrix, FaceMatrix, ValueMatrix and
417
- // LangMatrix so that all these data structure have predictable layouts.
418
- out .UidMatrix = append (out .UidMatrix , & pb.List {})
419
- out .FacetMatrix = append (out .FacetMatrix , & pb.FacetsList {})
420
- out .ValueMatrix = append (out .ValueMatrix ,
421
- & pb.ValueList {Values : []* pb.TaskValue {}})
422
- if q .ExpandAll {
423
- // To keep the cardinality same as that of ValueMatrix.
424
- out .LangMatrix = append (out .LangMatrix , & pb.LangList {})
443
+ // If count is being requested, there is no need to populate value and facets matrix.
444
+ if q .DoCount {
445
+ count , err := countForValuePostings (args , pl , facetsTree , listType )
446
+ if err != nil && err != posting .ErrNoValue {
447
+ return err
448
+ }
449
+ out .Counts = append (out .Counts , uint32 (count ))
450
+ // Add an empty UID list to make later processing consistent.
451
+ out .UidMatrix = append (out .UidMatrix , & pb.List {})
452
+ continue
425
453
}
426
- continue
427
- case err != nil :
428
- return err
429
- }
430
454
431
- if q .ExpandAll {
432
- langTags , err := pl .GetLangTags (args .q .ReadTs )
433
- if err != nil {
455
+ vals , fcs , err = retrieveValuesAndFacets (args , pl , facetsTree , listType )
456
+
457
+ switch {
458
+ case err == posting .ErrNoValue || (err == nil && len (vals ) == 0 ):
459
+ // This branch is taken when the value does not exist in the pl or
460
+ // the number of values retrieved is zero (there could still be facets).
461
+ // We add empty lists to the UidMatrix, FaceMatrix, ValueMatrix and
462
+ // LangMatrix so that all these data structure have predictable layouts.
463
+ out .UidMatrix = append (out .UidMatrix , & pb.List {})
464
+ out .FacetMatrix = append (out .FacetMatrix , & pb.FacetsList {})
465
+ out .ValueMatrix = append (out .ValueMatrix ,
466
+ & pb.ValueList {Values : []* pb.TaskValue {}})
467
+ if q .ExpandAll {
468
+ // To keep the cardinality same as that of ValueMatrix.
469
+ out .LangMatrix = append (out .LangMatrix , & pb.LangList {})
470
+ }
471
+ continue
472
+ case err != nil :
434
473
return err
435
474
}
436
- out .LangMatrix = append (out .LangMatrix , & pb.LangList {Lang : langTags })
475
+
476
+ if q .ExpandAll {
477
+ langTags , err := pl .GetLangTags (args .q .ReadTs )
478
+ if err != nil {
479
+ return err
480
+ }
481
+ out .LangMatrix = append (out .LangMatrix , & pb.LangList {Lang : langTags })
482
+ }
437
483
}
438
484
439
485
uidList := new (pb.List )
0 commit comments