xapian-core  2.1.0
inmemory_database.cc
Go to the documentation of this file.
1 
4 /* Copyright 1999,2000,2001 BrightStation PLC
5  * Copyright 2002 Ananova Ltd
6  * Copyright 2002-2026 Olly Betts
7  * Copyright 2006,2009 Lemur Consulting Ltd
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of the
12  * License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, see
21  * <https://www.gnu.org/licenses/>.
22  */
23 
24 #include <config.h>
25 
26 #include "inmemory_database.h"
27 
28 #include "debuglog.h"
29 
31 #include "clamp_cast.h"
32 #include "expand/expandweight.h"
33 #include "inmemory_document.h"
34 #include "inmemory_alltermslist.h"
35 #include "str.h"
36 #include "backends/valuestats.h"
37 
38 #include <algorithm>
39 #include <string>
40 #include <string_view>
41 #include <vector>
42 #include <map>
43 
44 #include <xapian/error.h>
45 #include <xapian/valueiterator.h>
46 
47 using namespace std;
49 
50 inline void
53  Xapian::termpos position,
54  bool use_position)
55 {
56  InMemoryPosting posting;
57  posting.did = did;
58 
59  // Find the right place in the sorted list.
60  vector<InMemoryPosting>::iterator p;
61  p = lower_bound(docs.begin(), docs.end(),
62  posting, InMemoryPostingLessThan());
63  if (p == docs.end() || InMemoryPostingLessThan()(posting, *p)) {
64  // Adding new entry.
65  if (use_position) {
66  posting.positions.push_back(position);
67  }
68  posting.wdf = wdf;
69  posting.valid = true;
70  docs.insert(p, std::move(posting));
71  } else if (!p->valid) {
72  // Resurrecting deleted entry.
73  p->did = did;
74  p->positions.clear();
75  if (use_position) {
76  p->positions.push_back(position);
77  }
78  p->wdf = wdf;
79  p->valid = true;
80  } else if (use_position) {
81  // Adding position to existing entry.
82  p->add_position(position);
83  }
84 }
85 
86 inline void
89  Xapian::termpos position,
90  bool use_position)
91 {
92  InMemoryTermEntry termentry;
93  termentry.term = term;
94 
95  // Find the right place in the sorted list.
96  vector<InMemoryTermEntry>::iterator p;
97  p = lower_bound(terms.begin(), terms.end(),
98  termentry, InMemoryTermEntryLessThan());
99  if (p == terms.end() || InMemoryTermEntryLessThan()(termentry, *p)) {
100  // Adding new entry.
101  if (use_position) {
102  termentry.positions.push_back(position);
103  }
104  termentry.wdf = wdf;
105  terms.insert(p, std::move(termentry));
106  } else if (use_position) {
107  p->add_position(position);
108  }
109 }
110 
112 // Postlist //
114 
116  const InMemoryTerm & imterm,
117  std::string_view term_)
118  : LeafPostList(term_),
119  pos(imterm.docs.begin()),
120  end(imterm.docs.end()),
121  started(false),
122  db(db_),
123  wdf_upper_bound(0)
124 {
125  termfreq = imterm.term_freq;
126  collfreq = imterm.collection_freq;
127  while (pos != end && !pos->valid) ++pos;
128  if (pos != end) {
129  auto first_wdf = (*pos).wdf;
130  wdf_upper_bound = max(first_wdf, imterm.collection_freq - first_wdf);
131  }
132 }
133 
136 {
138  Assert(started);
139  Assert(!at_end());
140  return (*pos).did;
141 }
142 
143 PostList *
144 InMemoryPostList::next(double /*w_min*/)
145 {
147  if (started) {
148  Assert(!at_end());
149  ++pos;
150  while (pos != end && !pos->valid) ++pos;
151  } else {
152  started = true;
153  }
154  return NULL;
155 }
156 
157 PostList *
159 {
161  // FIXME - see if we can make more efficient, perhaps using better
162  // data structure. Note, though, that a binary search of
163  // the remaining list may NOT be a good idea (search time is then
164  // O(log {length of list}), as opposed to O(distance we want to skip)
165  // Since we will frequently only be skipping a short distance, this
166  // could well be worse.
167 
168  // If we've not started, it's OK to call skip_to().
169  Assert(!at_end() || !started);
170  started = true;
171  while (!at_end() && (*pos).did < did) {
172  (void) next(w_min);
173  }
174  return NULL;
175 }
176 
177 bool
179 {
181  return (pos == end);
182 }
183 
184 void
186  Xapian::docid& last) const
187 {
188  Assert(!started);
189  if (pos != end) {
190  first = pos->did;
191  last = (end - 1)->did;
192  } else {
193  last = 0;
194  }
195 }
196 
197 string
199 {
200  return term + ":" + str(termfreq);
201 }
202 
205 {
206  return db->get_wdfdocmax(get_docid());
207 }
208 
209 PositionList *
211 {
213  mypositions.assign(pos->positions.copy());
214  return &mypositions;
215 }
216 
217 PositionList *
219 {
221  if (pos->positions.empty()) return nullptr;
222  return new InMemoryPositionList(pos->positions.copy());
223 }
224 
227 {
229  return (*pos).wdf;
230 }
231 
234 {
236  return wdf_upper_bound;
237 }
238 
240 // Termlist //
242 
244  Xapian::docid did_,
245  const InMemoryDoc & doc,
246  Xapian::termcount len)
247  : pos(doc.terms.begin()), end(doc.terms.end()), terms(doc.terms.size()),
248  started(false), db(db_), did(did_), document_length(len)
249 {
250  LOGLINE(DB, "InMemoryTermList::InMemoryTermList(): " <<
251  terms << " terms starting from " << pos->term);
252 }
253 
256 {
258  Assert(started);
259  Assert(pos != end);
260  return (*pos).wdf;
261 }
262 
265 {
267  Assert(started);
268  Assert(pos != end);
269 
270  Xapian::doccount tf;
271  db->get_freqs((*pos).term, &tf, NULL);
272  return tf;
273 }
274 
277 {
279  return terms;
280 }
281 
282 void
284 {
286  Assert(started);
287  Assert(pos != end);
288  stats.accumulate(shard_index,
291  db->get_doccount());
292 }
293 
294 TermList *
296 {
298  if (started) {
299  Assert(pos != end);
300  ++pos;
301  } else {
302  started = true;
303  }
304  if (pos == end)
305  return this;
306  current_term = pos->term;
307  return NULL;
308 }
309 
310 TermList*
312 {
313  if (rare(db->is_closed()))
315 
316  while (pos != end && pos->term < term) {
317  ++pos;
318  }
319 
320  started = true;
321  if (pos == end)
322  return this;
323  current_term = pos->term;
324  return NULL;
325 }
326 
329 {
331  return db->positionlist_count(did, (*pos).term);
332 }
333 
336 {
338  return db->open_position_list(did, (*pos).term);
339 }
340 
342 // InMemoryAllDocsPostList //
344 
346  : LeafPostList({}), did(0), db(db_)
347 {
348  collfreq = termfreq = db->totdocs;
349 }
350 
353 {
355  Assert(did > 0);
356  Assert(did <= db->termlists.size());
357  Assert(db->termlists[did - 1].is_valid);
358  return did;
359 }
360 
363 {
364  return 1;
365 }
366 
367 PositionList *
369 {
370  throw Xapian::UnimplementedError("Can't open position list for all docs iterator");
371 }
372 
373 PositionList *
375 {
376  throw Xapian::UnimplementedError("Can't open position list for all docs iterator");
377 }
378 
379 PostList *
381 {
383  Assert(!at_end());
384  do {
385  ++did;
386  } while (did <= db->termlists.size() && !db->termlists[did - 1].is_valid);
387  return NULL;
388 }
389 
390 PostList *
392 {
394  Assert(!at_end());
395  if (did <= did_) {
396  did = did_;
397  while (did <= db->termlists.size() && !db->termlists[did - 1].is_valid) {
398  ++did;
399  }
400  }
401  return NULL;
402 }
403 
404 bool
406 {
408  return (did > db->termlists.size());
409 }
410 
413 {
414  return 1;
415 }
416 
417 string
419 {
420  return "InMemoryAllDocsPostList " + str(did);
421 }
422 
424 // Actual database class //
426 
427 // Updates are applied immediately so we can't support transactions.
429  : Xapian::Database::Internal(TRANSACTION_UNIMPLEMENTED),
430  totdocs(0), totlen(0), positions_present(false), closed(false)
431 {
432  // We keep an empty entry in postlists for convenience of implementing
433  // allterms iteration.
434  postlists.insert(make_pair(string(), InMemoryTerm()));
435 }
436 
438 {
439  dtor_called();
440 }
441 
442 bool
444 {
446  return false;
447 }
448 
449 void
451 {
452  // Free all the resources, and mark the db as closed.
453  postlists.clear();
454  termlists.clear();
455  doclists.clear();
456  valuelists.clear();
457  valuestats.clear();
458  doclengths.clear();
459  metadata.clear();
460  closed = true;
461 }
462 
463 PostList*
465 {
467 }
468 
471  bool need_read_pos) const
472 {
473  (void)need_read_pos;
475  if (term.empty()) {
476  Assert(!need_read_pos);
478  if (rare(doccount == 0)) {
479  return nullptr;
480  }
481  if (doccount == termlists.size()) {
482  // The used docid range is exactly 1 to doccount inclusive.
484  }
485  return new InMemoryAllDocsPostList(this);
486  }
487  auto i = postlists.find(term);
488  if (i == postlists.end() || i->second.term_freq == 0) {
489  return nullptr;
490  }
491  return new InMemoryPostList(this, i->second, term);
492 }
493 
494 bool
496 {
498  return (did > 0 && did <= termlists.size() && termlists[did - 1].is_valid);
499 }
500 
501 void
503  Xapian::doccount* termfreq_ptr,
504  Xapian::termcount* collfreq_ptr) const
505 {
507  auto i = postlists.find(term);
508  if (i != postlists.end()) {
509  if (termfreq_ptr)
510  *termfreq_ptr = i->second.term_freq;
511  if (collfreq_ptr)
512  *collfreq_ptr = i->second.collection_freq;
513  } else {
514  if (termfreq_ptr)
515  *termfreq_ptr = 0;
516  if (collfreq_ptr)
517  *collfreq_ptr = 0;
518  }
519 }
520 
523 {
525  auto i = valuestats.find(slot);
526  if (i == valuestats.end()) return 0;
527  return i->second.freq;
528 }
529 
530 std::string
532 {
534  auto i = valuestats.find(slot);
535  if (i == valuestats.end()) return string();
536  return i->second.lower_bound;
537 }
538 
539 std::string
541 {
543  auto i = valuestats.find(slot);
544  if (i == valuestats.end()) return string();
545  return i->second.upper_bound;
546 }
547 
550 {
551  // A zero-length document can't contain any terms, so we ignore such
552  // documents for the purposes of this lower bound.
553  return 1;
554 }
555 
558 {
559  // Not a very tight bound in general, but InMemory isn't really built for
560  // performance.
561  return clamp_cast<Xapian::termcount>(get_total_length());
562 }
563 
566 {
567  // Not a very tight bound in general, but InMemory isn't really built for
568  // performance.
570  get_freqs(term, NULL, &cf);
571  return cf;
572 }
573 
576 {
578  return totdocs;
579 }
580 
583 {
585  return Xapian::docid(termlists.size());
586 }
587 
590 {
591  return totlen;
592 }
593 
596 {
598  if (!doc_exists(did)) {
599  throw Xapian::DocNotFoundError(string("Docid ") + str(did) +
600  string(" not found"));
601  }
602  return doclengths[did - 1];
603 }
604 
607 {
609  if (did == 0 || did > termlists.size() || !termlists[did - 1].is_valid)
610  throw Xapian::DocNotFoundError(string("Docid ") + str(did) +
611  string(" not found"));
612  // get_unique_terms() really ought to only count terms with wdf > 0, but
613  // that's expensive to calculate on demand, so for now let's just ensure
614  // unique_terms <= doclen.
615  Xapian::termcount terms = termlists[did - 1].terms.size();
616  return std::min(terms, Xapian::termcount(doclengths[did - 1]));
617 }
618 
621 {
623  if (did == 0 || did > termlists.size() || !termlists[did - 1].is_valid)
624  throw Xapian::DocNotFoundError(string("Docid ") + str(did) +
625  string(" not found"));
626  Xapian::termcount max_wdf = 0;
627  for (auto&& i : termlists[did - 1].terms) {
628  if (i.wdf > max_wdf) max_wdf = i.wdf;
629  }
630  return max_wdf;
631 }
632 
633 TermList *
635 {
637  Assert(did != 0);
638  if (!doc_exists(did)) {
639  // FIXME: the docid in this message will be local, not global
640  throw Xapian::DocNotFoundError(string("Docid ") + str(did) +
641  string(" not found"));
642  }
644  termlists[did - 1], doclengths[did - 1]);
645 }
646 
647 TermList *
649 {
651 }
652 
655 {
657  Assert(did != 0);
658  if (!lazy && !doc_exists(did)) {
659  // FIXME: the docid in this message will be local, not global
660  throw Xapian::DocNotFoundError(string("Docid ") + str(did) +
661  string(" not found"));
662  }
663  return new InMemoryDocument(this, did);
664 }
665 
666 std::string
667 InMemoryDatabase::get_metadata(std::string_view key) const
668 {
670  auto i = metadata.find(key);
671  if (i == metadata.end())
672  return string();
673  return i->second;
674 }
675 
676 TermList *
678 {
680  if (metadata.empty()) return NULL;
681  // FIXME: nobody implemented this yet...
682  throw Xapian::UnimplementedError("InMemory backend doesn't currently implement Database::metadata_keys_begin()");
683 }
684 
685 void
686 InMemoryDatabase::set_metadata(std::string_view key,
687  std::string_view value)
688 {
690  if (!value.empty()) {
691 #ifdef __cpp_lib_associative_heterogeneous_insertion // C++26
692  metadata.insert_or_assign(key, value);
693 #else
694  metadata.insert_or_assign(string(key), value);
695 #endif
696  } else {
697 #ifdef __cpp_lib_associative_heterogeneous_erasure // C++23
698  metadata.erase(key);
699 #else
700  metadata.erase(string(key));
701 #endif
702  }
703 }
704 
707  string_view term) const
708 {
710  if (!doc_exists(did)) {
711  return 0;
712  }
713  const InMemoryDoc &doc = termlists[did - 1];
714 
715  InMemoryTermEntry temp;
716  temp.term = term;
717  auto t = lower_bound(doc.terms.begin(), doc.terms.end(),
718  temp, InMemoryTermEntryLessThan());
719  if (t != doc.terms.end() && t->term == term) {
720  return clamp_cast<Xapian::termcount>(t->positions.size());
721  }
722  return 0;
723 }
724 
727  string_view term) const
728 {
730  if (usual(doc_exists(did))) {
731  const InMemoryDoc &doc = termlists[did - 1];
732 
733  InMemoryTermEntry temp;
734  temp.term = term;
735  auto t = lower_bound(doc.terms.begin(), doc.terms.end(),
736  temp, InMemoryTermEntryLessThan());
737  if (t != doc.terms.end() && t->term == term) {
738  return new InMemoryPositionList(t->positions);
739  }
740  }
741  return nullptr;
742 }
743 
744 void
746  const map<Xapian::valueno, string> &values_)
747 {
749  if (did > valuelists.size()) {
750  valuelists.resize(did);
751  }
752  valuelists[did - 1] = values_;
753 
754  // Update the statistics.
755  for (auto&& j : values_) {
756  auto i = valuestats.insert(make_pair(j.first, ValueStats()));
757 
758  // Now, modify the stored statistics.
759  if ((i.first->second.freq)++ == 0) {
760  // If the value count was previously zero, set the upper and lower
761  // bounds to the newly added value.
762  i.first->second.lower_bound = j.second;
763  i.first->second.upper_bound = j.second;
764  } else {
765  // Otherwise, simply make sure they reflect the new value.
766  if (j.second < i.first->second.lower_bound) {
767  i.first->second.lower_bound = j.second;
768  }
769  if (j.second > i.first->second.upper_bound) {
770  i.first->second.upper_bound = j.second;
771  }
772  }
773  }
774 }
775 
776 // We implicitly commit each modification right away, so nothing to do here.
777 void
779 {
780 }
781 
782 // We implicitly commit each modification right away, so nothing to do here.
783 void
785 {
786 }
787 
788 void
790 {
792  if (!doc_exists(did)) {
793  throw Xapian::DocNotFoundError(string("Docid ") + str(did) +
794  string(" not found"));
795  }
796  termlists[did - 1].is_valid = false;
797  doclists[did - 1] = string();
798  for (auto&& j : valuelists[did - 1]) {
799  auto i = valuestats.find(j.first);
800  if (--(i->second.freq) == 0) {
801  i->second.lower_bound.resize(0);
802  i->second.upper_bound.resize(0);
803  }
804  }
805  valuelists[did - 1].clear();
806 
807  totlen -= doclengths[did - 1];
808  doclengths[did - 1] = 0;
809  totdocs--;
810  // A crude check, but it's hard to be more precise with the current
811  // InMemory structure without being very inefficient.
812  if (totdocs == 0) positions_present = false;
813 
814  for (auto&& i : termlists[did - 1].terms) {
815  auto t = postlists.find(i.term);
816  Assert(t != postlists.end());
817  t->second.collection_freq -= i.wdf;
818  --t->second.term_freq;
819 
820  // Just invalidate erased doc ids - otherwise we need to erase
821  // in a vector (inefficient) and we break any posting lists
822  // iterating over this posting list.
823  InMemoryPosting temp;
824  temp.did = did;
825  auto p = lower_bound(t->second.docs.begin(), t->second.docs.end(),
826  temp, InMemoryPostingLessThan());
827  if (p != t->second.docs.end() && p->did == did) {
828  p->valid = false;
829  }
830  }
831  termlists[did - 1].terms.clear();
832 }
833 
834 void
836  const Xapian::Document & document)
837 {
838  LOGCALL_VOID(DB, "InMemoryDatabase::replace_document", did | document);
839 
841 
842  if (doc_exists(did)) {
843  for (auto&& j : valuelists[did - 1]) {
844  auto i = valuestats.find(j.first);
845  if (--(i->second.freq) == 0) {
846  i->second.lower_bound.resize(0);
847  i->second.upper_bound.resize(0);
848  }
849  }
850 
851  totlen -= doclengths[did - 1];
852  totdocs--;
853  } else if (did > termlists.size()) {
854  termlists.resize(did);
855  termlists[did - 1].is_valid = true;
856  doclengths.resize(did);
857  doclists.resize(did);
858  valuelists.resize(did);
859  } else {
860  termlists[did - 1].is_valid = true;
861  }
862 
863  for (auto&& i : termlists[did - 1].terms) {
864  auto t = postlists.find(i.term);
865  Assert(t != postlists.end());
866  t->second.collection_freq -= i.wdf;
867  --t->second.term_freq;
868 
869  // Just invalidate erased doc ids - otherwise we need to erase
870  // in a vector (inefficient) and we break any posting lists
871  // iterating over this posting list.
872  InMemoryPosting temp;
873  temp.did = did;
874  auto p = lower_bound(t->second.docs.begin(), t->second.docs.end(),
875  temp, InMemoryPostingLessThan());
876  if (p != t->second.docs.end() && p->did == did) {
877  p->valid = false;
878  }
879  }
880 
881  doclengths[did - 1] = 0;
882  doclists[did - 1] = document.get_data();
883 
884  finish_add_doc(did, document);
885 }
886 
889 {
890  LOGCALL(DB, Xapian::docid, "InMemoryDatabase::add_document", document);
892 
893  Xapian::docid did = make_doc(document.get_data());
894 
895  finish_add_doc(did, document);
896 
897  RETURN(did);
898 }
899 
900 void
902 {
903  {
904  map<Xapian::valueno, string> values;
905  Xapian::ValueIterator k = document.values_begin();
906  for ( ; k != document.values_end(); ++k) {
907  values.insert(make_pair(k.get_valueno(), *k));
908  LOGLINE(DB, "InMemoryDatabase::finish_add_doc(): adding value " <<
909  k.get_valueno() << " -> " << *k);
910  }
911  add_values(did, values);
912  }
913 
914  InMemoryDoc doc(true);
915  Xapian::TermIterator i = document.termlist_begin();
916  for ( ; i != document.termlist_end(); ++i) {
917  make_term(*i);
918 
919  LOGLINE(DB, "InMemoryDatabase::finish_add_doc(): adding term " << *i);
921  if (j == i.positionlist_end()) {
922  /* Make sure the posting exists, even without a position. */
923  make_posting(&doc, *i, did, 0, i.get_wdf(), false);
924  } else {
925  positions_present = true;
926  for ( ; j != i.positionlist_end(); ++j) {
927  make_posting(&doc, *i, did, *j, i.get_wdf());
928  }
929  }
930 
931  Assert(did > 0 && did <= doclengths.size());
932  doclengths[did - 1] += i.get_wdf();
933  totlen += i.get_wdf();
934  postlists[*i].collection_freq += i.get_wdf();
935  ++postlists[*i].term_freq;
936  }
937  swap(termlists[did - 1], doc);
938 
939  totdocs++;
940 }
941 
942 void
944 {
945  postlists[term]; // Initialise, if not already there.
946 }
947 
949 InMemoryDatabase::make_doc(const string & docdata)
950 {
951  if (rare(termlists.size() == Xapian::docid(-1))) {
952  // Really unlikely to actually happen for inmemory.
953  throw Xapian::DatabaseError("Run out of docids");
954  }
955  termlists.push_back(InMemoryDoc(true));
956  doclengths.push_back(0);
957  doclists.push_back(docdata);
958 
959  AssertEqParanoid(termlists.size(), doclengths.size());
960 
961  return Xapian::docid(termlists.size());
962 }
963 
965  const string& term,
966  Xapian::docid did,
967  Xapian::termpos position,
968  Xapian::termcount wdf,
969  bool use_position)
970 {
971  Assert(doc);
972  Assert(postlists.find(term) != postlists.end());
973  Assert(did > 0 && did <= termlists.size());
974  Assert(did > 0 && did <= doclengths.size());
975  Assert(doc_exists(did));
976 
977  postlists[term].add_posting(did, wdf, position, use_position);
978  doc->add_posting(term, wdf, position, use_position);
979 }
980 
981 bool
983 {
985  if (term.empty()) {
986  return totdocs != 0;
987  }
988  auto i = postlists.find(term);
989  if (i == postlists.end()) return false;
990  return (i->second.term_freq != 0);
991 }
992 
993 bool
995 {
997  return positions_present;
998 }
999 
1000 TermList*
1001 InMemoryDatabase::open_allterms(string_view prefix) const
1002 {
1004  return new InMemoryAllTermsList(&postlists,
1006  prefix);
1007 }
1008 
1009 void
1011  Xapian::docid& last) const
1012 {
1014  first = 1;
1015  last = Xapian::docid(termlists.size());
1016  if (last == 0 || last == totdocs) {
1017  // Empty database or contiguous range starting at 1.
1018  return;
1019  }
1020  while (!termlists[first - 1].is_valid) ++first;
1021  while (!termlists[last - 1].is_valid) --last;
1022 }
1023 
1026 {
1027  // InMemoryDatabase doesn't really distinguish writable and read-only.
1028  return this;
1029 }
1030 
1031 void
1033 {
1034  throw Xapian::DatabaseClosedError("Database has been closed");
1035 }
1036 
1037 string
1039 {
1040  return "InMemory";
1041 }
1042 
1043 #ifdef DISABLE_GPL_LIBXAPIAN
1044 # error GPL source we cannot relicense included in libxapian
1045 #endif
Cast a value to a type, clamping out of range values.
A PostList iterating all docids when they form a contiguous range.
PositionList * open_position_list() const
Read the position list for the term in the current document and return a pointer to it (not owned by ...
PostList * skip_to(Xapian::docid did, double w_min)
Skip forward to the specified docid.
Xapian::docid get_docid() const
Return the current docid.
Xapian::Internal::intrusive_ptr< const InMemoryDatabase > db
bool at_end() const
Return true if the current position is past the last entry in this list.
InMemoryAllDocsPostList(const InMemoryDatabase *db)
Xapian::termcount get_wdf() const
Return the wdf for the document at the current position.
std::string get_description() const
Return a string description of this object.
Xapian::termcount get_wdf_upper_bound() const
PositionList * read_position_list()
Read the position list for the term in the current document and return a pointer to it (owned by the ...
class for alltermslists over several databases
A database held entirely in memory.
Xapian::termcount get_wdfdocmax(Xapian::docid did) const
Get the max wdf in document.
std::string get_value_upper_bound(Xapian::valueno slot) const
Get an upper bound on the values stored in the given value slot.
static void throw_database_closed()
TermList * open_term_list_direct(Xapian::docid did) const
Like open_term_list() but without MultiTermList wrapper.
Xapian::termcount get_doclength(Xapian::docid did) const
TermList * open_term_list(Xapian::docid did) const
Xapian::termcount get_wdf_upper_bound(std::string_view term) const
Get an upper bound on the wdf of term term.
std::vector< InMemoryDoc > termlists
Xapian::termcount get_doclength_lower_bound() const
Get a lower bound on the length of a document in this DB.
TermList * open_metadata_keylist(std::string_view prefix) const
Open a termlist returning each metadata key.
void commit()
Implementation of virtual methods: see Database for details.
std::vector< Xapian::termcount > doclengths
void cancel()
Cancel pending modifications to the database.
std::string get_value_lower_bound(Xapian::valueno slot) const
Get a lower bound on the values stored in the given value slot.
void replace_document(Xapian::docid did, const Xapian::Document &document)
Xapian::doccount get_value_freq(Xapian::valueno slot) const
Return the frequency of a given value slot.
void get_used_docid_range(Xapian::docid &first, Xapian::docid &last) const
Find lowest and highest docids actually in use.
std::string get_description() const
Return a string describing this object.
void add_values(Xapian::docid did, const std::map< Xapian::valueno, std::string > &values_)
std::map< Xapian::valueno, ValueStats > valuestats
Xapian::docid add_document(const Xapian::Document &document)
Xapian::docid get_lastdocid() const
Return the last used document id of this (sub) database.
void delete_document(Xapian::docid did)
Xapian::termcount positionlist_count(Xapian::docid did, std::string_view term) const
LeafPostList * open_leaf_post_list(std::string_view term, bool need_read_pos) const
Create a LeafPostList for use during a match.
Xapian::docid make_doc(const std::string &docdata)
PostList * open_post_list(std::string_view term) const
Return a PostList suitable for use in a PostingIterator.
bool reopen()
Reopen the database to the latest available revision.
Xapian::Database::Internal * update_lock(int flags)
Lock a read-only database for writing or unlock a writable database.
PositionList * open_position_list(Xapian::docid did, std::string_view term) const
void make_posting(InMemoryDoc *doc, const std::string &term, Xapian::docid did, Xapian::termpos position, Xapian::termcount wdf, bool use_position=true)
Xapian::termcount get_unique_terms(Xapian::docid did) const
Get the number of unique terms in document.
bool doc_exists(Xapian::docid did) const
std::vector< std::string > doclists
Xapian::Document::Internal * open_document(Xapian::docid did, bool lazy) const
Open a handle on a document.
Xapian::doccount get_doccount() const
bool term_exists(std::string_view term) const
void close()
Close the database.
bool is_closed() const
TermList * open_allterms(std::string_view prefix) const
friend class InMemoryDocument
std::map< std::string, std::string, std::less<> > metadata
Xapian::totallength totlen
void make_term(const std::string &term)
std::map< std::string, InMemoryTerm, std::less<> > postlists
Xapian::doccount totdocs
std::vector< std::map< Xapian::valueno, std::string > > valuelists
friend class InMemoryAllDocsPostList
void finish_add_doc(Xapian::docid did, const Xapian::Document &document)
void set_metadata(std::string_view key, std::string_view value)
Set the metadata associated with a given key.
Xapian::termcount get_doclength_upper_bound() const
Get an upper bound on the length of a document in this DB.
void get_freqs(std::string_view term, Xapian::doccount *termfreq_ptr, Xapian::termcount *collfreq_ptr) const
Returns frequencies for a term.
std::string get_metadata(std::string_view key) const
Get the metadata associated with a given key.
Xapian::totallength get_total_length() const
Return the total length of all documents in this database.
bool has_positions() const
Check whether this database contains any positional information.
InMemoryDatabase()
Create and open an in-memory database.
Class representing a document and the terms indexing it.
void add_posting(const std::string &term, Xapian::termcount wdf, Xapian::termpos position, bool use_position)
std::vector< InMemoryTermEntry > terms
PositionList from an InMemory DB or a Document object.
void assign(Xapian::VecCOW< Xapian::termpos > &&positions_)
Move assign positional data.
A PostList in an inmemory database.
std::string get_description() const
Return a string description of this object.
Xapian::termcount wdf_upper_bound
Xapian::docid get_docid() const
Return the current docid.
InMemoryPositionList mypositions
List of positions of the current term.
InMemoryPostList(const InMemoryDatabase *db, const InMemoryTerm &imterm, std::string_view term_)
void get_docid_range(Xapian::docid &first, Xapian::docid &last) const
Get the bounds on the range of docids this PostList can return.
PostList * skip_to(Xapian::docid did, double w_min)
Skip forward to the specified docid.
Xapian::termcount get_wdf() const
Return the wdf for the document at the current position.
Xapian::termcount get_wdfdocmax() const
std::vector< InMemoryPosting >::const_iterator pos
bool at_end() const
Return true if the current position is past the last entry in this list.
PositionList * open_position_list() const
Read the position list for the term in the current document and return a pointer to it (not owned by ...
Xapian::Internal::intrusive_ptr< const InMemoryDatabase > db
PositionList * read_position_list()
Read the position list for the term in the current document and return a pointer to it (owned by the ...
Xapian::termcount get_wdf_upper_bound() const
std::vector< InMemoryPosting >::const_iterator end
Xapian::VecCOW< Xapian::termpos > positions
Xapian::docid did
Xapian::termcount wdf
Xapian::VecCOW< Xapian::termpos > positions
Xapian::termcount wdf
InMemoryTermList(Xapian::Internal::intrusive_ptr< const InMemoryDatabase > db, Xapian::docid did, const InMemoryDoc &doc, Xapian::termcount len)
Xapian::termcount get_approx_size() const
Return approximate size of this termlist.
Xapian::termcount get_wdf() const
Return the wdf for the term at the current position.
void accumulate_stats(Xapian::Internal::ExpandStats &stats) const
Collate weighting information for the current term.
Xapian::doccount get_termfreq() const
Return the term frequency for the term at the current position.
Xapian::Internal::intrusive_ptr< const InMemoryDatabase > db
TermList * next()
Advance the current position to the next term in the termlist.
std::vector< InMemoryTermEntry >::const_iterator pos
Xapian::termcount terms
TermList * skip_to(std::string_view term)
Skip forward to the specified term.
Xapian::termcount document_length
std::vector< InMemoryTermEntry >::const_iterator end
Xapian::termcount positionlist_count() const
Return the length of the position list for the current position.
PositionList * positionlist_begin() const
Return PositionList for the current position.
Xapian::termcount collection_freq
void add_posting(Xapian::docid did, Xapian::termcount wdf, Xapian::termpos position, bool use_position)
Xapian::termcount term_freq
Abstract base class for leaf postlists.
Definition: leafpostlist.h:40
Xapian::termcount collfreq
The collection frequency of the term.
Definition: leafpostlist.h:57
std::string term
The term name for this postlist (empty for an alldocs postlist).
Definition: leafpostlist.h:51
Indicates an attempt to access a closed database.
Definition: error.h:1085
DatabaseError indicates some sort of database related error.
Definition: error.h:355
Virtual base class for Database internals.
void dtor_called()
Helper to process uncommitted changes when a writable db is destroyed.
Indicates an attempt to access a document not present in the database.
Definition: error.h:662
Abstract base class for a document.
Class representing a document.
Definition: document.h:64
std::string get_data() const
Get the document data.
Definition: document.cc:75
ValueIterator values_begin() const
Start iterating the values in this document.
Definition: document.cc:208
TermIterator termlist_end() const noexcept
End iterator corresponding to termlist_begin().
Definition: document.h:219
TermIterator termlist_begin() const
Start iterating the terms in this document.
Definition: document.cc:179
ValueIterator values_end() const noexcept
End iterator corresponding to values_begin().
Definition: document.h:259
Collates statistics while calculating term weight in an ESet.
Definition: expandweight.h:37
void accumulate(size_t shard_index, Xapian::termcount wdf, Xapian::termcount doclen, Xapian::doccount subtf, Xapian::doccount subdbsize)
Definition: expandweight.h:71
Abstract base class for postlists.
Definition: postlist.h:40
PostList * next()
Advance the current position to the next document in the postlist.
Definition: postlist.h:168
Xapian::doccount termfreq
Estimate of the number of documents this PostList will return.
Definition: postlist.h:52
A smart pointer that uses intrusive reference counting.
Definition: intrusive_ptr.h:83
Abstract base class for iterating term positions in a document.
Definition: positionlist.h:32
Class for iterating over term positions.
Abstract base class for termlists.
Definition: termlist.h:42
std::string current_term
The current term.
Definition: termlist.h:54
size_t shard_index
Which shard of a multidatabase this is from.
Definition: termlist.h:126
Class for iterating over a list of terms.
Definition: termiterator.h:41
PositionIterator positionlist_end() const noexcept
Return an end PositionIterator for the current term.
Definition: termiterator.h:109
Xapian::termcount get_wdf() const
Return the wdf for the term at the current position.
PositionIterator positionlist_begin() const
Return a PositionIterator for the current term.
UnimplementedError indicates an attempt to use an unimplemented feature.
Definition: error.h:313
Class for iterating over document values.
Definition: valueiterator.h:39
Xapian::valueno get_valueno() const
Return the value slot number for the current position.
#define usual(COND)
Definition: config.h:617
#define rare(COND)
Definition: config.h:616
Iterate all document ids when they form a contiguous range.
string term
PositionList * p
Xapian::termpos pos
Debug logging macros.
#define RETURN(...)
Definition: debuglog.h:484
#define LOGCALL(CATEGORY, TYPE, FUNC, PARAMS)
Definition: debuglog.h:478
#define LOGLINE(a, b)
Definition: debuglog.h:485
#define LOGCALL_VOID(CATEGORY, FUNC, PARAMS)
Definition: debuglog.h:479
Hierarchy of classes which Xapian can throw as exceptions.
Collate statistics and calculate the term weights for the ESet.
Iterate all terms in an inmemory db.
C++ class definition for inmemory database access.
A document read from a InMemoryDatabase.
string str(int value)
Convert int to std::string.
Definition: str.cc:91
The Xapian namespace contains public interfaces for the Xapian library.
Definition: compactor.cc:82
unsigned XAPIAN_TERMCOUNT_BASE_TYPE termcount
A counts of terms.
Definition: types.h:64
unsigned valueno
The number for a value slot in a document.
Definition: types.h:90
unsigned XAPIAN_DOCID_BASE_TYPE doccount
A count of documents.
Definition: types.h:37
unsigned XAPIAN_DOCID_BASE_TYPE docid
A unique identifier for a document.
Definition: types.h:51
unsigned XAPIAN_TERMPOS_BASE_TYPE termpos
A term position within a document or query.
Definition: types.h:75
XAPIAN_TOTALLENGTH_TYPE totallength
The total length of all documents in a database.
Definition: types.h:112
#define AssertEqParanoid(A, B)
Definition: omassert.h:131
#define Assert(COND)
Definition: omassert.h:122
Convert types to std::string.
Class to hold statistics for a given slot.
Definition: valuestats.h:28
Class for iterating over document values.
Statistics about values.