diff options
author | Aleksey Lim <alsroot@sugarlabs.org> | 2012-03-13 18:06:16 (GMT) |
---|---|---|
committer | Aleksey Lim <alsroot@sugarlabs.org> | 2012-03-13 18:06:16 (GMT) |
commit | 6156ff9dab937fcbba1a22e9579e93c785d10738 (patch) | |
tree | 9596efbc8af2fec5f049d4d17d071390dea53f7a | |
parent | d05e1afd30a511778238789ff79605c671210f2f (diff) |
Reproduce index behaviour in cache for searching by composite properties
-rw-r--r-- | active_document/index_proxy.py | 59 | ||||
-rwxr-xr-x | tests/units/index.py | 19 | ||||
-rwxr-xr-x | tests/units/index_proxy.py | 43 |
3 files changed, 107 insertions, 14 deletions
diff --git a/active_document/index_proxy.py b/active_document/index_proxy.py index 40e98e4..cd99f2d 100644 --- a/active_document/index_proxy.py +++ b/active_document/index_proxy.py @@ -131,8 +131,17 @@ class IndexProxy(IndexReader): terms = set() for prop_name, value in request.items(): - if _is_term(self.metadata[prop_name]): - terms.add((prop_name, value)) + prop = self.metadata[prop_name] + if not _is_term(prop): + continue + try: + value = prop.convert(value) + except ValueError, error: + _logger.debug('Wrong request property value %r for "%s" ' \ + 'property, thus the whole request is empty: %s', + value, prop_name, error) + return None, None, None + terms.add(_TermValue(prop, value)) for cache in self._cache.values(): if cache.new: @@ -192,15 +201,17 @@ class _CachedDocument(object): self.new = new self.terms = set() self.orig_terms = set() - self._term_names = [] + self._term_props = [] if not new: record = Storage(metadata).get(guid) for prop_name, prop in metadata.items(): - if _is_term(prop): - self._term_names.append(prop_name) - if not new: - self.orig_terms.add((prop_name, record.get(prop_name))) + if not _is_term(prop): + continue + self._term_props.append(prop) + if not new: + self.orig_terms.add(_TermValue(prop, record.get(prop_name))) + self._update_terms() def __sort__(self, other): @@ -212,10 +223,36 @@ class _CachedDocument(object): def _update_terms(self): self.terms.clear() - orig_terms = dict(self.orig_terms) - for prop_name in self._term_names: - term = self.properties.get(prop_name, orig_terms.get(prop_name)) - self.terms.add((prop_name, term)) + orig_terms = {} + for i in self.orig_terms: + orig_terms[i.prop] = i.value + for prop in self._term_props: + term = self.properties.get(prop.name, orig_terms.get(prop)) + self.terms.add(_TermValue(prop, term)) + + +class _TermValue: + + def __init__(self, prop, value): + self.prop = prop + self.value = value + + def __cmp__(self, other): + result = cmp(self.prop.name, other.prop.name) + if result: + return result + if not self.prop.composite: + return cmp(self.value, other.value) + self_value = set(self.value) + other_value = set(other.value) + if self_value.issubset(other_value) or \ + other_value.issubset(self_value): + return 0 + else: + return cmp(self.value, other.value) + + def __hash__(self): + return hash(self.prop.name) def _is_term(prop): diff --git a/tests/units/index.py b/tests/units/index.py index 0749b41..6d14701 100755 --- a/tests/units/index.py +++ b/tests/units/index.py @@ -508,6 +508,25 @@ class IndexTest(tests.Test): ([{'guid': '1'}], 1), db._find(query='%s:=test' % term, reply=['guid'])) + def test_find_WithListProps(self): + db = Index({'prop': ActiveProperty('prop', None, 'A', full_text=True, typecast=[])}) + + db.store('1', {'prop': ('a', )}, True) + db.store('2', {'prop': ('a', 'aa')}, True) + db.store('3', {'prop': ('aa', 'aaa')}, True) + + self.assertEqual( + ([{'guid': '1'}, {'guid': '2'}], 2), + db._find(request={'prop': 'a'}, reply=['prop'])) + + self.assertEqual( + ([{'guid': '2'}, {'guid': '3'}], 2), + db._find(request={'prop': 'aa'})) + + self.assertEqual( + ([{'guid': '3'}], 1), + db._find(request={'prop': 'aaa'})) + class Index(index.IndexWriter): diff --git a/tests/units/index_proxy.py b/tests/units/index_proxy.py index cc1ed03..17175cc 100755 --- a/tests/units/index_proxy.py +++ b/tests/units/index_proxy.py @@ -21,6 +21,9 @@ class IndexProxyTest(tests.Test): def setUp(self): tests.Test.setUp(self) + self.Document = None + + def setup_document(self): class Document(document.Document): @@ -69,12 +72,14 @@ class IndexProxyTest(tests.Test): self.wait_job = gevent.spawn(waiter) def tearDown(self): - assert not self.committed - self.wait_job.kill() + if self.Document is not None: + assert not self.committed + self.wait_job.kill() + self.Document.close() tests.Test.tearDown(self) - self.Document.close() def test_Create(self): + self.setup_document() proxy = IndexProxy(self.metadata) self.assertEqual( @@ -138,6 +143,7 @@ class IndexProxyTest(tests.Test): proxy._find()[0]) def test_Update(self): + self.setup_document() proxy = IndexProxy(self.metadata) proxy._store(self.doc_1, {'term': '1_term_2'}) @@ -151,6 +157,7 @@ class IndexProxyTest(tests.Test): proxy._find()[0]) def test_Update_Adds(self): + self.setup_document() proxy = IndexProxy(self.metadata) self.assertEqual( @@ -181,6 +188,7 @@ class IndexProxyTest(tests.Test): proxy._find()[0]) def test_Update_Deletes(self): + self.setup_document() proxy = IndexProxy(self.metadata) self.assertEqual( @@ -204,6 +212,7 @@ class IndexProxyTest(tests.Test): proxy._find(request={'common': 'common'})) def test_Get(self): + self.setup_document() doc = self.Document(term='3', not_term='3', common='3') doc.post() @@ -213,6 +222,7 @@ class IndexProxyTest(tests.Test): self.assertEqual('3', doc_2.common) def test_Document_merge(self): + self.setup_document() ts = int(time.time()) self.Document.merge(self.doc_1.guid, { @@ -263,6 +273,33 @@ class IndexProxyTest(tests.Test): del self.committed[:] + def test_FindByListProps(self): + + class Document2(document.Document): + + @active_property(prefix='A', typecast=[]) + def prop(self, value): + return value + + index_queue.close() + Document2.init(IndexProxy) + index_queue.init([Document2]) + proxy = IndexProxy(Document2.metadata) + + proxy.store('1', {'ctime': 0, 'mtime': 0, 'seqno': 0, 'prop': ('a',)}, True) + proxy.store('2', {'ctime': 0, 'mtime': 0, 'seqno': 0, 'prop': ('a', 'aa')}, True) + proxy.store('3', {'ctime': 0, 'mtime': 0, 'seqno': 0, 'prop': ('aa', 'aaa')}, True) + + self.assertEqual( + ['1', '2'], + [i['guid'] for i in proxy._find(request={'prop': 'a'})[0]]) + self.assertEqual( + ['2', '3'], + [i['guid'] for i in proxy._find(request={'prop': 'aa'})[0]]) + self.assertEqual( + ['3'], + [i['guid'] for i in proxy._find(request={'prop': 'aaa'})[0]]) + class IndexProxy(index_proxy.IndexProxy): |