1 #$Id: indexer_common.py,v 1.11 2008-09-11 19:41:07 schlatterbeck Exp $
3 # Python 2.3 ... 2.6 compatibility:
4 from roundup
.anypy
.sets_
import set
6 from roundup
import hyperdb
9 "A", "AND", "ARE", "AS", "AT", "BE", "BUT", "BY",
10 "FOR", "IF", "IN", "INTO", "IS", "IT",
11 "NO", "NOT", "OF", "ON", "OR", "SUCH",
12 "THAT", "THE", "THEIR", "THEN", "THERE", "THESE",
13 "THEY", "THIS", "TO", "WAS", "WILL", "WITH"
16 def _isLink(propclass
):
17 return (isinstance(propclass
, hyperdb
.Link
) or
18 isinstance(propclass
, hyperdb
.Multilink
))
21 def __init__(self
, db
):
22 self
.stopwords
= set(STOPWORDS
)
23 for word
in db
.config
[('main', 'indexer_stopwords')]:
24 self
.stopwords
.add(word
)
25 # Do not index anything longer than 25 characters since that'll be
26 # gibberish (encoded text or somesuch) or shorter than 2 characters
30 def is_stopword(self
, word
):
31 return word
in self
.stopwords
33 def getHits(self
, search_terms
, klass
):
34 return self
.find(search_terms
)
36 def search(self
, search_terms
, klass
, ignore
={}):
37 """Display search results looking for [search, terms] associated
38 with the hyperdb Class "klass". Ignore hits on {class: property}.
41 hits
= self
.getHits(search_terms
, klass
)
45 designator_propname
= {}
46 for nm
, propclass
in klass
.getprops().iteritems():
47 if _isLink(propclass
):
48 designator_propname
.setdefault(propclass
.classname
,
51 # build a dictionary of nodes and their associated messages
53 nodeids
= {} # this is the answer
54 propspec
= {} # used to do the klass.find
55 for l
in designator_propname
.itervalues():
57 propspec
[propname
] = {} # used as a set (value doesn't matter)
59 # don't unpack hits entries as sqlite3's Row can't be unpacked :(
61 # skip this result if we don't care about this class/property
64 if (classname
, property) in ignore
:
67 # if it's a property on klass, it's easy
68 # (make sure the nodeid is str() not unicode() as returned by some
69 # backends as that can cause problems down the track)
70 nodeid
= str(entry
[1])
71 if classname
== klass
.classname
:
72 if nodeid
not in nodeids
:
76 # make sure the class is a linked one, otherwise ignore
77 if classname
not in designator_propname
:
80 # it's a linked class - set up to do the klass.find
81 for linkprop
in designator_propname
[classname
]:
82 propspec
[linkprop
][nodeid
] = 1
84 # retain only the meaningful entries
85 for propname
, idset
in list(propspec
.items()):
87 del propspec
[propname
]
89 # klass.find tells me the klass nodeids the linked nodes relate to
90 propdefs
= klass
.getprops()
91 for resid
in klass
.find(**propspec
):
94 continue # we ignore duplicate resids
96 node_dict
= nodeids
[resid
]
97 # now figure out where it came from
98 for linkprop
in propspec
:
99 v
= klass
.get(resid
, linkprop
)
100 # the link might be a Link so deal with a single result or None
101 if isinstance(propdefs
[linkprop
], hyperdb
.Link
):
102 if v
is None: continue
105 if nodeid
in propspec
[linkprop
]:
106 # OK, this node[propname] has a winner
107 if linkprop
not in node_dict
:
108 node_dict
[linkprop
] = [nodeid
]
110 node_dict
[linkprop
].append(nodeid
)