Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Implement range queries.

  • Loading branch information...
commit b5ae4a65cfa313a6f6e5b95793bf83dbc35fe4c6 1 parent f4c731a
authored February 23, 2013
37  db/xapian_music.py
@@ -5,23 +5,22 @@
5 5
 from db.dirtree import get_songs
6 6
 import json
7 7
 import os
  8
+import time
8 9
 
9 10
 # a mapping of query term/aliases → xapian prefixes.
10 11
 # most of these are also keys to the song[] dict.
11 12
 # Prefixes from http://xapian.org/docs/omega/termprefixes.html
12 13
 PREFIXES = {'artist' : 'A',
13 14
             'title' : 'S',
14  
-            'year' : 'Y',
15 15
             'path' : 'U',
16 16
             'album' : 'XALBUM',
17  
-            'mtime' : 'XMTIME',
18  
-            'title' : 'XTITLE',
19  
-            'tracknumber' : 'XTRACKNR'}
  17
+            'title' : 'XTITLE'}
20 18
 
21  
-NUMERIC_PREFIXES = {}
22  
-
23  
-# Use slot #1 for tags
24  
-#XAPIAN_TAGS = 1
  19
+# These numeric prefixes will also be used as data slots.
  20
+NUMERIC_PREFIXES = {'year' : 'Y',
  21
+                    'mtime' : 'XMTIME',
  22
+                    'tracknumber' : 'XTRACKNR',
  23
+                    'rating' : 'XRATING'}
25 24
 
26 25
 def index(datapath, dbpath):
27 26
     # Create or open the database we're going to be writing to.
@@ -31,6 +30,18 @@ def index(datapath, dbpath):
31 30
     termgenerator = xapian.TermGenerator()
32 31
     termgenerator.set_stemmer(xapian.Stem("en"))
33 32
 
  33
+    def make_value(s, term):
  34
+        "Parse various string values and return suitable numeric representations."
  35
+        if term == 'year':
  36
+            # This is in a date string format due to serialization.
  37
+            return xapian.sortable_serialise(int(s))
  38
+        if term == 'mtime':
  39
+            return xapian.sortable_serialise(time.mktime(time.strptime(s)))
  40
+        if term == 'rating':
  41
+            return xapian.sortable_serialise(max([float(n) for n in s]))
  42
+        else:
  43
+            return xapian.sortable_serialise(int(s))
  44
+
34 45
     for song in get_songs(datapath):
35 46
         # We make a document and tell the term generator to use this.
36 47
         doc = xapian.Document()
@@ -46,6 +57,11 @@ def index(datapath, dbpath):
46 57
             #if pos < len(term):
47 58
             termgenerator.increase_termpos()
48 59
 
  60
+        for data_slot, term in enumerate(NUMERIC_PREFIXES):
  61
+            if song[term]:
  62
+                doc.add_value(data_slot, make_value(song[term], term))
  63
+                
  64
+
49 65
         # Store all the fields for display purposes.
50 66
         doc.set_data(unicode(json.dumps(song)))
51 67
 
@@ -77,6 +93,11 @@ def parse_query(q):
77 93
     for term in PREFIXES:
78 94
         queryparser.add_prefix(term, PREFIXES[term])
79 95
 
  96
+    for data_slot, term in enumerate(NUMERIC_PREFIXES):
  97
+        queryparser.add_valuerangeprocessor(
  98
+            xapian.NumberValueRangeProcessor(data_slot, term, True)
  99
+        )
  100
+
80 101
     # And parse the query
81 102
     return queryparser.parse_query(q)    
82 103
 
17  test/test.py
@@ -291,7 +291,22 @@ def test_search_genre():
291 291
   assert False
292 292
 
293 293
 def test_search_year_interval():
294  
-  assert False
  294
+
  295
+  def search_interval_year(db):
  296
+    q_all = 'year..3000'
  297
+    q_2010 = 'year..2010'
  298
+    q_1999 = 'year..1999'
  299
+    q_early_00s = 'year1999..2004'
  300
+    songs_all = search(db, q_all)
  301
+    songs_2010 = search(db, q_2010)
  302
+    songs_1999 = search(db, q_1999)
  303
+    songs_early_00s = search(db, q_early_00s)
  304
+    assert len(songs_all) == 6
  305
+    assert len(songs_2010) == 5
  306
+    assert len(songs_1999) == 0
  307
+    assert len(songs_early_00s) == 2
  308
+    
  309
+  with_index(search_interval_year)
295 310
 
296 311
 def test_search_rating_interval():
297 312
   assert False

0 notes on commit b5ae4a6

Please sign in to comment.
Something went wrong with that request. Please try again.