rangexapian

Does Xapian support query string like "x: 1..2 OR x: 8..10"? I cannot figure it out


Following is my simple code, index function establishes indexers and search function searches using querystring directly:

#include <xapian.h>
#include <stdlib.h>

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

int index() {
    try {
        Xapian::WritableDatabase db("./index.db", Xapian::DB_CREATE_OR_OPEN);
        Xapian::TermGenerator indexer;
        Xapian::Stem stemmer("english");
        indexer.set_stemmer(stemmer);

        for (int i = 1; i < 12; i++) {
            Xapian::Document doc;
            indexer.set_document(doc);

            string title("title ");
            string desc("example data with number of ");
            stringstream num;

            num << i;
            title.append(num.str());
            desc.append(num.str());

            indexer.index_text(title, 1, "S");
            indexer.index_text(desc, 1, "XD");

            indexer.index_text(title);
            indexer.increase_termpos();
            indexer.index_text(desc);

            doc.set_data(num.str() + "\n" + title + "\n" + desc);
            doc.add_value(1, num.str());

            string idterm = "Q" + num.str();
            doc.add_boolean_term(idterm);
            db.add_document(doc);
        }

        db.commit();
    } catch (const Xapian::Error &e) {
        cout << e.get_description() << endl;

        return 1;
    }

    return 0;
}

int search() {
    try {
        Xapian::Database db("./index.db");

        Xapian::Enquire enquire(db);
        // Xapian::Query query("");
        Xapian::Query queryLeft(Xapian::Query::OP_VALUE_RANGE, 1, "1", "2");
        Xapian::Query queryRight(Xapian::Query::OP_VALUE_RANGE, 1, "8", "11");
        Xapian::Query query(Xapian::Query::OP_OR, queryLeft, queryRight);

        cout << "Parsed query is: " << query.get_description() << endl;
        enquire.set_query(query);

        Xapian::MSet matches = enquire.get_mset(0, 11);

        cout << matches.get_matches_estimated() << " results found.\n";
        cout << "Matches 1-" << matches.size() << ":\n" << endl;

        for (Xapian::MSetIterator i = matches.begin(); i != matches.end();
                ++i) {
            cout << i.get_rank() + 1 << ":" << i.get_percent() << "%" << endl;
            cout << i.get_document().get_data() << endl << endl;
        }
    } catch (const Xapian::Error &e) {
        cout << e.get_description() << endl;

        return 1;
    }

    return 0;
}

int main() {
    index();
    search();
}

run the app, I got:

Parsed query is: Xapian::Query((VALUE_RANGE 1 1 2 OR VALUE_RANGE 1 8 11))
8 results found.
Matches 1-8:

1:100%
1
title 1
example data with number of 1

2:100%
2
title 2
example data with number of 2

3:100%
10
title 10
example data with number of 10

4:100%
11
title 11
example data with number of 11

5:100%
1
title 1
example data with number of 1

6:100%
2
title 2
example data with number of 2

7:100%
10
title 10
example data with number of 10

8:100%
11
title 11
example data with number of 11

Actually I want to get:

1:100%
1
title 1
example data with number of 1

2:100%
2
title 2
example data with number of 2

8:100% #8
8
title 8
example data with number of 8

9:100%
9
title 9
example data with number of 9

10:100%
10
title 10
example data with number of 10

Did I make some mistakes? or missed something or just used wrong query string?

PS: I am a beginner learning to Xapian.


Solution

  • Thank you, @jkalden, @James Aylett. I just got the results I want. Yes, Xapian::sortable_serialise() is key to solve my problem.

    #include <xapian.h>
    #include <stdlib.h>
    
    #include <iostream>
    #include <sstream>
    #include <string>
    
    using namespace std;
    
    int index() {
        try {
            Xapian::WritableDatabase db("./index.db", Xapian::DB_CREATE_OR_OPEN);
            Xapian::TermGenerator indexer;
            Xapian::Stem stemmer("english");
            indexer.set_stemmer(stemmer);
    
            for (int i = 1; i < 12; i++) {
                Xapian::Document doc;
                indexer.set_document(doc);
    
                string title("title ");
                string desc("example data with number of ");
                stringstream num;
    
                num << i;
                title.append(num.str());
                desc.append(num.str());
    
                indexer.index_text(title, 1, "S");
                indexer.index_text(desc, 1, "XD");
    
                indexer.index_text(title);
                indexer.increase_termpos();
                indexer.index_text(desc);
    
                doc.set_data(num.str() + "\n" + title + "\n" + desc);
                doc.add_value(0, Xapian::sortable_serialise(i));
    
                string idterm = "Q" + num.str();
                doc.add_boolean_term(idterm);
                db.add_document(doc);
            }
    
            db.commit();
        } catch (const Xapian::Error &e) {
            cout << e.get_description() << endl;
    
            return 1;
        }
    
        return 0;
    }
    
    int search() {
        try {
            Xapian::Database db("./index.db");
    
            Xapian::Enquire enquire(db);
            Xapian::Query queryLeft(Xapian::Query::OP_VALUE_RANGE, 0,
                    Xapian::sortable_serialise(1), Xapian::sortable_serialise(2));
            Xapian::Query queryRight(Xapian::Query::OP_VALUE_RANGE, 0,
                    Xapian::sortable_serialise(8), Xapian::sortable_serialise(11));
            Xapian::Query query(Xapian::Query::OP_OR, queryLeft, queryRight);
    
            cout << "Parsed query is: " << query.get_description() << endl;
            enquire.set_query(query);
    
            Xapian::MSet matches = enquire.get_mset(0, 10);
    
            cout << matches.get_matches_estimated() << " results found.\n";
            cout << "Matches 1-" << matches.size() << ":\n" << endl;
    
            for (Xapian::MSetIterator i = matches.begin(); i != matches.end();
                    ++i) {
                cout << i.get_rank() + 1 << ":" << i.get_percent() << "%" << endl;
                cout << i.get_document().get_data() << endl << endl;
            }
        } catch (const Xapian::Error &e) {
            cout << e.get_description() << endl;
    
            return 1;
        }
    
        return 0;
    }
    
    int main() {
        index();
        search();
    }
    

    Following is the output:

    Parsed query is: Xapian::Query((VALUE_RANGE 0 � � OR VALUE_RANGE 0 � ��))
    6 results found.
    Matches 1-6:
    
    1:100%
    1
    title 1
    example data with number of 1
    
    2:100%
    2
    title 2
    example data with number of 2
    
    3:100%
    8
    title 8
    example data with number of 8
    
    4:100%
    9
    title 9
    example data with number of 9
    
    5:100%
    10
    title 10
    example data with number of 10
    
    6:100%
    11
    title 11
    example data with number of 11