/** @file * @brief Class representing a document */ /* Copyright (C) 2010,2015,2016,2017,2018,2019,2023,2024 Olly Betts * Copyright 2009 Lemur Consulting Ltd * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see * . */ #ifndef XAPIAN_INCLUDED_DOCUMENT_H #define XAPIAN_INCLUDED_DOCUMENT_H #if !defined XAPIAN_IN_XAPIAN_H && !defined XAPIAN_LIB_BUILD # error Never use directly; include instead. #endif #include #include #include #include #include #include #include #include namespace Xapian { /** Class representing a document. * * The term "document" shouldn't be taken too literally - really it's a "thing * to retrieve", as the list of search results is essentially a list of * documents. * * Document objects fetch information from the database lazily. Usually * this behaviour isn't visible to users (except for the speed benefits), but * if the document in the database is modified or deleted then preexisting * Document objects may return the old or new versions of data (or throw * Xapian::DocNotFoundError in the case of deletion). * * Since Database objects work on a snapshot of the database's state, the * situation above can only happen with a WritableDatabase object, or if * you call Database::reopen() on the Database object which you got the * Document from. * * We recommend you avoid designs where this behaviour is an issue, but if * you need a way to make a non-lazy version of a Document object, you can do * this like so: * * doc = Xapian::Document::unserialise(doc.serialise()); */ class XAPIAN_VISIBILITY_DEFAULT Document { public: /// Class representing the Document internals. class Internal; /// @private @internal Reference counted internals. Xapian::Internal::intrusive_ptr_nonnull internal; /// @private @internal Wrap an existing Internal. XAPIAN_VISIBILITY_INTERNAL explicit Document(Internal*); /** Copy constructor. * * The internals are reference counted, so copying is cheap. */ Document(const Document& o); /** Assignment operator. * * The internals are reference counted, so assignment is cheap. */ Document& operator=(const Document& o); /// Move constructor. Document(Document&& o); /// Move assignment operator. Document& operator=(Document&& o); /** Default constructor. * * Creates an empty Document. */ Document(); /// Destructor. ~Document(); /** Get the document ID this document came from. * * If this document didn't come from a database, this will be 0 (in Xapian * 1.0.22/1.2.4 or later; prior to this the returned value was uninitialised * in this case). * * Note that if the document came from a sharded database, this is the docid * in the shard it came from, not the docid in the combined database. */ Xapian::docid get_docid() const; /// Get the document data. std::string get_data() const; /** Set the document data. * * This is an opaque blob as far as Xapian is concerned - it's up to you * to impose whatever structure you want on it. If you want to store * structured data, consider using something like protocol buffers. */ void set_data(std::string_view data); /// Add a term to this document. void add_term(std::string_view term, Xapian::termcount wdf_inc = 1); /** Add a boolean filter term to the document. * * This method adds @a term to the document with wdf of 0 - * this is generally what you want for a term used for boolean * filtering as the wdf of such terms is ignored, and it doesn't * make sense for them to contribute to the document's length. * * If the specified term already indexes this document, this method * has no effect. * * It is exactly the same as add_term(term, 0) and is provided as a * way to make a common operation more explicit. * * @param term The term to add. * * @since This method was added in Xapian 1.0.18. * */ void add_boolean_term(std::string_view term) { add_term(term, 0); } /// Remove a term from this document. void remove_term(std::string_view term); /// Add a posting for a term. void add_posting(std::string_view term, Xapian::termpos term_pos, Xapian::termcount wdf_inc = 1); /** Remove posting for a term. * * The instance of the specified term at position term_pos will be * removed, and the @a wdf reduced by @a wdf_dec (the wdf will not * ever go below zero though - the resultant wdf is clamped to zero * if it would). * * If the term doesn't occur at position term_pos then * Xapian::InvalidArgumentError is thrown. If you want to remove a single * position which may not be present without triggering an exception you * can call remove_postings(term, pos, pos) instead. * * Since 2.0.0, if the final position is removed and the wdf becomes zero * then the term will be removed from the document. */ void remove_posting(std::string_view term, Xapian::termpos term_pos, Xapian::termcount wdf_dec = 1); /** Remove a range of postings for a term. * * Any instances of the term at positions >= @a term_pos_first and * <= @a term_pos_last will be removed, and the wdf reduced by * @a wdf_dec for each instance removed (the wdf will not ever go * below zero though - the resultant wdf is clamped to zero if it would). * * If the term doesn't occur in the range of positions specified (including * if term_pos_first > term_pos_last) then this method does nothing (unlike * @a remove_posting() which throws an exception if the specified position * is not present). * * Since 2.0.0, if all remaining positions are removed and the wdf becomes * zero then the term will be removed from the document. Note that this * only happens if some positions are removed though - calling this method * on a term which has no positions and zero wdf won't remove that term. * * @return The number of postings removed. * * @since Added in Xapian 1.4.8. */ Xapian::termpos remove_postings(std::string_view term, Xapian::termpos term_pos_first, Xapian::termpos term_pos_last, Xapian::termcount wdf_dec = 1); /// Clear all terms from the document. void clear_terms(); /// Return the number of distinct terms in this document. Xapian::termcount termlist_count() const; /** Start iterating the terms in this document. * * The terms are returned in ascending string order (by byte value). * * Note that if the Document object came from a sharded database then * the TermIterator returned by this method only knows about the shard * the document came from so calling get_termfreq() on it will give * you the term frequency in that shard rather than in the combined * database. */ TermIterator termlist_begin() const; /// End iterator corresponding to @a termlist_begin(). TermIterator termlist_end() const noexcept { return TermIterator(); } /** Read a value slot in this document. * * @param slot The slot to read the value from * * @return The value in slot @a slot, or an empty string if not set. */ std::string get_value(Xapian::valueno slot) const; /** Add a value to a slot in this document. * * @param slot The slot to set * @param value The new value */ void add_value(Xapian::valueno slot, std::string_view value); /** Remove any value from the specified slot. * * @param slot The slot to remove any value from. */ void remove_value(Xapian::valueno slot) { add_value(slot, {}); } /// Clear all value slots in this document. void clear_values(); /// Count the value slots used in this document. Xapian::valueno values_count() const; /** Start iterating the values in this document. * * The values are returned in ascending numerical slot order. */ ValueIterator values_begin() const; /// End iterator corresponding to @a values_begin(). ValueIterator values_end() const noexcept { return ValueIterator(); } /** Efficiently swap this Document object with another. * * @since Added in Xapian 2.0.0. */ void swap(Document& o) { internal.swap(o.internal); } /** Serialise document into a string. * * The document representation may change between Xapian releases: even * between minor versions. However, it is guaranteed not to change if the * remote database protocol has not changed between releases. */ std::string serialise() const; /** Unserialise a document from a string produced by serialise(). */ static Document unserialise(std::string_view serialised); /// Return a string describing this object. std::string get_description() const; }; } #endif // XAPIAN_INCLUDED_DOCUMENT_H