Skip to content

Commit

Permalink
Implement range queries.
Browse files Browse the repository at this point in the history
  • Loading branch information
Albin Stjerna committed Feb 23, 2013
1 parent f4c731a commit b5ae4a6
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 9 deletions.
37 changes: 29 additions & 8 deletions db/xapian_music.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,22 @@
from db.dirtree import get_songs
import json
import os
import time

# a mapping of query term/aliases → xapian prefixes.
# most of these are also keys to the song[] dict.
# Prefixes from http://xapian.org/docs/omega/termprefixes.html
PREFIXES = {'artist' : 'A',
'title' : 'S',
'year' : 'Y',
'path' : 'U',
'album' : 'XALBUM',
'mtime' : 'XMTIME',
'title' : 'XTITLE',
'tracknumber' : 'XTRACKNR'}
'title' : 'XTITLE'}

NUMERIC_PREFIXES = {}

# Use slot #1 for tags
#XAPIAN_TAGS = 1
# These numeric prefixes will also be used as data slots.
NUMERIC_PREFIXES = {'year' : 'Y',
'mtime' : 'XMTIME',
'tracknumber' : 'XTRACKNR',
'rating' : 'XRATING'}

def index(datapath, dbpath):
# Create or open the database we're going to be writing to.
Expand All @@ -31,6 +30,18 @@ def index(datapath, dbpath):
termgenerator = xapian.TermGenerator()
termgenerator.set_stemmer(xapian.Stem("en"))

def make_value(s, term):
"Parse various string values and return suitable numeric representations."
if term == 'year':
# This is in a date string format due to serialization.
return xapian.sortable_serialise(int(s))
if term == 'mtime':
return xapian.sortable_serialise(time.mktime(time.strptime(s)))
if term == 'rating':
return xapian.sortable_serialise(max([float(n) for n in s]))
else:
return xapian.sortable_serialise(int(s))

for song in get_songs(datapath):
# We make a document and tell the term generator to use this.
doc = xapian.Document()
Expand All @@ -46,6 +57,11 @@ def index(datapath, dbpath):
#if pos < len(term):
termgenerator.increase_termpos()

for data_slot, term in enumerate(NUMERIC_PREFIXES):
if song[term]:
doc.add_value(data_slot, make_value(song[term], term))


# Store all the fields for display purposes.
doc.set_data(unicode(json.dumps(song)))

Expand Down Expand Up @@ -77,6 +93,11 @@ def parse_query(q):
for term in PREFIXES:
queryparser.add_prefix(term, PREFIXES[term])

for data_slot, term in enumerate(NUMERIC_PREFIXES):
queryparser.add_valuerangeprocessor(
xapian.NumberValueRangeProcessor(data_slot, term, True)
)

# And parse the query
return queryparser.parse_query(q)

Expand Down
17 changes: 16 additions & 1 deletion test/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,22 @@ def test_search_genre():
assert False

def test_search_year_interval():
assert False

def search_interval_year(db):
q_all = 'year..3000'
q_2010 = 'year..2010'
q_1999 = 'year..1999'
q_early_00s = 'year1999..2004'
songs_all = search(db, q_all)
songs_2010 = search(db, q_2010)
songs_1999 = search(db, q_1999)
songs_early_00s = search(db, q_early_00s)
assert len(songs_all) == 6
assert len(songs_2010) == 5
assert len(songs_1999) == 0
assert len(songs_early_00s) == 2

with_index(search_interval_year)

def test_search_rating_interval():
assert False
Expand Down

0 comments on commit b5ae4a6

Please sign in to comment.