Changeset 191

Show
Ignore:
Timestamp:
08/16/08 23:51:24 (11 months ago)
Author:
rgrp
Message:

[shakespeare/search][m]: more support search in WUI.

Location:
trunk/shakespeare
Files:
5 modified

Legend:

Unmodified
Added
Removed
  • trunk/shakespeare/controllers/search.py

    r170 r191  
    1010 
    1111    def index(self): 
    12         query = request.params.get('query', '') 
    13         if query: 
    14             c.matches = self._get_results(query) 
     12        c.query = request.params.get('query', '') 
     13        if c.query: 
     14            c.matches = self._get_matches(c.query) 
     15            c.results = self._get_results(c.matches) 
    1516            c.total = c.matches.get_matches_estimated() 
    1617        else: 
     
    1819        return render('search/index') 
    1920     
    20     def _get_results(self, query): 
     21    def _get_matches(self, query): 
    2122        index = shakespeare.search.SearchIndex.default_index() 
    22         matches = index.search(query) 
     23        matches = index.search(query, numresults=50) 
    2324        return matches 
    24          
    2525 
     26    def _get_results(self, matches): 
     27        results = [] 
     28        for m in matches: 
     29            text, lineno = self._match_to_text(m) 
     30            if text: 
     31                # slight hack -- just attach direct to object 
     32                text._lineno = lineno 
     33                text._snippet = m.document.get_data() 
     34                results.append(text) 
     35            else: 
     36                # TODO: create a dummy text ... 
     37                pass 
     38        return results 
     39 
     40    def _match_to_text(self, m): 
     41        item_id = m.document.get_value(shakespeare.search.ITEM_ID) 
     42        text = model.Material.byName(item_id) 
     43        lineno = m.document.get_value(shakespeare.search.LINE_NO) 
     44        return (text, lineno) 
     45 
  • trunk/shakespeare/search.py

    r189 r191  
    3636import xapian 
    3737 
     38# keys for document values 
     39ITEM_ID = 0 
     40LINE_NO = 1 
     41 
    3842class SearchIndex(object): 
    3943    def __init__(self, index_dir): 
     
    5862        return SearchIndex(index_dir) 
    5963 
    60     def add_item(self, fileobj): 
    61         document = xapian.WritableDatabase (self.index_dir, xapian.DB_CREATE_OR_OPEN) 
     64    def add_item(self, fileobj, item_id=None): 
     65        database = xapian.WritableDatabase(self.index_dir, xapian.DB_CREATE_OR_OPEN) 
    6266        indexer = xapian.TermGenerator() 
    6367        stemmer = xapian.Stem("english") 
     
    6670        para = '' 
    6771        try: 
     72            count = -1 
     73            para_start = 0 
    6874            for line in fileobj: 
     75                count += 1 
    6976                line = line.strip() 
    7077                if line == '': 
     
    7279                        doc = xapian.Document() 
    7380                        doc.set_data(para) 
     81                        id_term = 'I' + str(item_id) 
     82                        doc.add_term(id_term) 
     83                        doc.add_value(ITEM_ID, str(item_id)) 
     84                        doc.add_value(LINE_NO, str(para_start)) 
    7485 
    7586                        indexer.set_document(doc) 
     
    7788                        indexer.index_text(para) 
    7889 
    79                         # Add the document to the database. 
    80                         document.add_document(doc) 
     90                        database.add_document(doc) 
     91                        # assume next para starts 
    8192                        para = '' 
     93                    # must come after 
     94                    para_start = count 
    8295                else: 
    8396                    if para != '': 
     
    8699        except StopIteration: 
    87100            # TODO: what is happening here? 
    88             pass 
     101            raise 
    89102 
    90     def search(self, query_string): 
    91         # Open the database for searching. 
     103    def get_database(self): 
    92104        database = xapian.Database(self.index_dir) 
     105        return database 
    93106 
    94             # Start an enquire session. 
     107    def search(self, query_string, offset=0, numresults=10): 
     108        database = self.get_database() 
    95109        enquire = xapian.Enquire(database) 
    96  
    97         # Parse the query string to produce a Xapian::Query object. 
    98110        qp = xapian.QueryParser() 
    99111        stemmer = xapian.Stem("english") 
     
    102114        qp.set_stemming_strategy(xapian.QueryParser.STEM_SOME) 
    103115        query = qp.parse_query(query_string) 
    104         print "Parsed query is: %s" % query.get_description() 
    105  
    106          # Find the top 10 results for the query. 
    107116        enquire.set_query(query) 
    108         # get search results offset, offset+count 
    109         offset = 0 
    110         count = 10 
    111         matches = enquire.get_mset(offset, count) 
     117        matches = enquire.get_mset(offset, numresults) 
    112118        return matches 
    113119 
     
    126132            works = [ path ] 
    127133        for work in works: 
    128             if self.verbose: 
    129                 print 'Processing %s' % work 
    130134            fileobj = open(work) 
    131             self.index.add_item(fileobj) 
     135            self.add_item(fileobj) 
    132136 
    133137    @classmethod 
     
    144148            msg += '\n' 
    145149        return msg 
    146  
    147  
     150     
  • trunk/shakespeare/templates/search/index.html

    r181 r191  
    1111 
    1212    <div class="search-results" py:if="c.matches is not None"> 
    13       <h3>Search Results</h3> 
     13      <h3>Search Results For: ${c.query}</h3> 
    1414      There were ${c.total} results. 
    1515      <ul> 
    16         <li py:for="m in c.matches"> 
    17         ${m.document.get_data()} 
     16        <li py:for="m in c.results"> 
     17        Work: ${m.title}, Line: ${m._lineno} 
     18        <blockquote> 
     19          <pre>${m._snippet}</pre> 
     20        </blockquote> 
    1821        </li> 
    1922      </ul> 
  • trunk/shakespeare/tests/functional/test_search.py

    r189 r191  
    1111        text = make_fixture() 
    1212        sindex = shakespeare.search.SearchIndex.default_index() 
    13         sindex.add_item(StringIO.StringIO(text.content)) 
     13        sindex.add_item(StringIO.StringIO(text.content), text.name) 
    1414 
    1515    def test_index(self): 
     
    2424        form['query'] = 'summer' 
    2525        res = form.submit() 
     26        # print res 
    2627        assert 'Search Results' in res 
    2728        assert 'Shall I compare thee' in res 
  • trunk/shakespeare/tests/test_search.py

    r189 r191  
    55 
    66import shakespeare.search 
     7import shakespeare.tests 
    78 
    89class TestSearch: 
    9     # break up a little to make indexing more interesting 
    10     text = \ 
    11 ''' 
    12 Shall I compare thee to a summer's day? 
    13 Thou art more lovely and more temperate: 
    14 Rough winds do shake the darling buds of May, 
    15 And summer's lease hath all too short a date: 
    16  
    17 Sometime too hot the eye of heaven shines, 
    18 And often is his gold complexion dimm'd, 
    19 And every fair from fair sometime declines, 
    20 By chance, or nature's changing course untrimm'd:  
    21  
    22 But thy eternal summer shall not fade, 
    23 Nor lose possession of that fair thou ow'st, 
    24 Nor shall death brag thou wander'st in his shade, 
    25 When in eternal lines to time thou grow'st, 
    26  
    27   So long as men can breathe, or eyes can see, 
    28   So long lives this, and this gives life to thee. 
    29 ''' 
    30  
    3110    def setUp(self): 
     11        self.text = shakespeare.tests.make_fixture() 
    3212        basetmp = tempfile.gettempdir() 
    3313        self.tmpdir = os.path.join(basetmp, 'openshkspr-search') 
     
    3717        os.makedirs(self.tmpdir) 
    3818        self.index = shakespeare.search.SearchIndex(self.tmpdir) 
     19        self.index.add_item(StringIO.StringIO(self.text.content), 
     20                self.text.name) 
     21 
     22    # TODO: remove the document from the index 
    3923 
    4024    def test_add_item(self): 
    41         self.index.add_item(StringIO.StringIO(self.text)) 
     25        assert self.index.get_database().get_doccount() > 0 
    4226 
    4327    def test_search(self): 
    44         self.index.add_item(StringIO.StringIO(self.text)) 
    4528        out = self.index.search('summer') 
    4629        assert len(out) == 2 
     
    5134        out = self.index.search('rough') 
    5235        assert len(out) == 1 
     36     
     37    def test_retrieve_lineno(self): 
     38        out = self.index.search('summer') 
     39        mset1 = out[1] 
     40        lineno = mset1.document.get_value(shakespeare.search.LINE_NO) 
     41        assert lineno == '9' 
    5342 
     43    def test_retrieve_itemid(self): 
     44        out = self.index.search('summer') 
     45        mset1 = out[1] 
     46        name = mset1.document.get_value(shakespeare.search.ITEM_ID) 
     47        assert name == self.text.name 
     48