private ReadResult Reduce(IDictionary <long, SortedList <long, byte> > query, ReadSession readSession, int skip, int take) { IDictionary <long, BOCHit> scored = new Dictionary <long, BOCHit>(); foreach (var term in query) { var hit = Scan(term.Key, term.Value); BOCHit score; if (scored.TryGetValue(hit.PostingsOffsets.PostingsOffset, out score)) { scored[hit.Key].Score = score.Score + hit.Value.Score; } else { scored.Add(hit.Key, hit.Value); } } var sortedHits = scored.Values.OrderByDescending(h => h.Score); var offsets = sortedHits.Select(h => h.PostingsOffset).ToArray(); var docIds = _postingsReader.Read(skip, take, offsets); var window = docIds.GroupBy(x => x).Select(x => (x.Key, x.Count())) .OrderByDescending(x => x.Item2) .Skip(skip) .Take(take) .Select(x => x.Key).ToList(); var docs = readSession.ReadDocs(window); return(new ReadResult { Docs = docs, Total = docIds.Count }); }
private async Task <IDictionary <ulong, float> > DoRead(Query query) { try { IDictionary <ulong, float> result = null; var cursor = query; while (cursor != null) { var keyHash = cursor.Term.Key.ToString().ToHash(); var ix = GetIndex(keyHash); if (ix != null) { var queryTerm = new VectorNode(cursor.Term.Value.ToString()); var match = ix.ClosestMatch(queryTerm); if (match.Score > 0) { if (match.Node.PostingsOffset < 0) { throw new InvalidDataException(); } var docIds = (await _postingsReader.Read(CollectionId, match.Node.PostingsOffset)) .ToDictionary(x => x, y => match.Score); if (result == null) { result = docIds; } else { if (cursor.And) { var aggregatedResult = new Dictionary <ulong, float>(); foreach (var doc in result) { float score; if (docIds.TryGetValue(doc.Key, out score)) { aggregatedResult[doc.Key] = score + doc.Value; } } result = aggregatedResult; } else if (cursor.Not) { foreach (var id in docIds.Keys) { result.Remove(id); } } else // Or { foreach (var id in docIds) { float score; if (result.TryGetValue(id.Key, out score)) { result[id.Key] = score + id.Value; } else { result.Add(id.Key, id.Value); } } } } } } cursor = cursor.Next; } _log.Log("query {0} matched {1} docs", query.Term, result == null ? 0 : result.Count); return(result); } catch (Exception ex) { _log.Log(ex); throw; } }