Building the search¶
Now we have our database populated with some values, it is time for the code to search the database and display some results.
We want to take some text from the user, and search for it in the database; to do that we need to convert it into a Xapian Query, which you will recall is a tree made up of terms (which in this case will be the stemmed forms of words in the text from the user), and operations such as AND, OR and so forth.
There are many ways to go from the user’s text to a Query, but the most simple of these is to use the QueryParser. We then pass the Query to an Enquire object, which also needs setting up with a database, and is where you’d set various other options that affect how the query is run (such as sorting, for instance) which we won’t address here.
def search(dbpath, querystring, offset=0, pagesize=10):
# offset - defines starting point within result set
# pagesize - defines number of records to retrieve
# Open the database we're going to search.
db = xapian.Database(dbpath)
# Set up a QueryParser with a stemmer and suitable prefixes
queryparser = xapian.QueryParser()
queryparser.set_stemmer(xapian.Stem("en"))
queryparser.set_stemming_strategy(queryparser.STEM_SOME)
# Start of prefix configuration.
queryparser.add_prefix("title", "S")
queryparser.add_prefix("description", "XD")
# End of prefix configuration.
# And parse the query
query = queryparser.parse_query(querystring)
# Use an Enquire object on the database to run the query
enquire = xapian.Enquire(db)
enquire.set_query(query)
# And print out something about each match
matches = []
for match in enquire.get_mset(offset, pagesize):
fields = json.loads(match.document.get_data().decode('utf8'))
print(u"%(rank)i: #%(docid)3.3i %(title)s" % {
'rank': match.rank + 1,
'docid': match.docid,
'title': fields.get('TITLE', u''),
})
matches.append(match.docid)
# Finally, make sure we log the query and displayed results
support.log_matches(querystring, offset, pagesize, matches)
A full copy of this code is available in code/python3/search1.py.