From 2b3bb81fae128bafa7b860088bd8c20bf53de942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wilson=20J=C3=BAnior?= Date: Sat, 29 Nov 2014 23:48:58 -0200 Subject: [PATCH] Refactoring: `Simple is better than complex` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Wilson JĂșnior --- mongoengine/base/document.py | 12 +++++++++++- mongoengine/queryset/base.py | 31 +++++++------------------------ tests/queryset/queryset.py | 5 ++--- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/mongoengine/base/document.py b/mongoengine/base/document.py index 5063dee5..998e366f 100644 --- a/mongoengine/base/document.py +++ b/mongoengine/base/document.py @@ -68,7 +68,7 @@ class BaseDocument(object): # Exception. if not self._dynamic: for var in values.keys(): - if var not in self._fields.keys() + ['id', 'pk', '_cls']: + if var not in self._fields.keys() + ['id', 'pk', '_cls', '_text_score']: msg = ( "The field '{0}' does not exist on the document '{1}'" ).format(var, self._class_name) @@ -281,6 +281,16 @@ class BaseDocument(object): """ pass + def get_text_score(self): + """ + Get text score from text query + """ + + if '_text_score' not in self._data: + raise InvalidDocumentError('This document is not originally built from a text query') + + return self._data['_text_score'] + def to_mongo(self, use_db_field=True, fields=[]): """ Return as SON data ready for use with MongoDB. diff --git a/mongoengine/queryset/base.py b/mongoengine/queryset/base.py index 7887ef3f..39ffa88f 100644 --- a/mongoengine/queryset/base.py +++ b/mongoengine/queryset/base.py @@ -6,7 +6,6 @@ import operator import pprint import re import warnings -import types from bson import SON from bson.code import Code @@ -38,8 +37,6 @@ PULL = 4 RE_TYPE = type(re.compile('')) -def get_text_score(doc): - return doc._data.get('_text_score') class BaseQuerySet(object): @@ -69,7 +66,6 @@ class BaseQuerySet(object): self._as_pymongo = False self._as_pymongo_coerce = False self._search_text = None - self._include_text_scores = False # If inheritance is allowed, only return instances and instances of # subclasses of the class being used @@ -161,13 +157,8 @@ class BaseQuerySet(object): if queryset._as_pymongo: return queryset._get_as_pymongo(queryset._cursor[key]) - doc = queryset._document._from_son(queryset._cursor[key], - _auto_dereference=self._auto_dereference, only_fields=self.only_fields) - - if self._include_text_scores: - doc.get_text_score = types.MethodType(get_text_score, doc) - - return doc + return queryset._document._from_son(queryset._cursor[key], + _auto_dereference=self._auto_dereference, only_fields=self.only_fields) raise AttributeError @@ -201,7 +192,7 @@ class BaseQuerySet(object): """ return self.__call__(*q_objs, **query) - def search_text(self, text, language=None, include_text_scores=True): + def search_text(self, text, language=None): """ Start a text search, using text indexes. Require: MongoDB server version 2.6+. @@ -210,14 +201,11 @@ class BaseQuerySet(object): for the search and the rules for the stemmer and tokenizer. If not specified, the search uses the default language of the index. For supported languages, see `Text Search Languages `. - - :param include_text_scores: If True, automatically add a get_text_score method to Document. - """ queryset = self.clone() if queryset._search_text: raise OperationError( - "Is not possible to use search_text two times.") + "It is not possible to use search_text two times.") query_kwargs = SON({'$search': text}) if language: @@ -227,7 +215,6 @@ class BaseQuerySet(object): queryset._mongo_query = None queryset._cursor_obj = None queryset._search_text = text - queryset._include_text_scores = include_text_scores return queryset @@ -684,7 +671,7 @@ class BaseQuerySet(object): '_timeout', '_class_check', '_slave_okay', '_read_preference', '_iter', '_scalar', '_as_pymongo', '_as_pymongo_coerce', '_limit', '_skip', '_hint', '_auto_dereference', - '_search_text', '_include_text_scores', 'only_fields', '_max_time_ms') + '_search_text', 'only_fields', '_max_time_ms') for prop in copy_props: val = getattr(self, prop) @@ -1351,9 +1338,6 @@ class BaseQuerySet(object): doc = self._document._from_son(raw_doc, _auto_dereference=self._auto_dereference, only_fields=self.only_fields) - if self._include_text_scores: - doc.get_text_score = types.MethodType(get_text_score, doc) - if self._scalar: return self._get_scalar(doc) @@ -1362,6 +1346,7 @@ class BaseQuerySet(object): def rewind(self): """Rewind the cursor to its unevaluated state. + .. versionadded:: 0.3 """ self._iter = False @@ -1389,7 +1374,7 @@ class BaseQuerySet(object): if self._loaded_fields: cursor_args['fields'] = self._loaded_fields.as_dict() - if self._include_text_scores: + if self._search_text: if 'fields' not in cursor_args: cursor_args['fields'] = {} @@ -1608,8 +1593,6 @@ class BaseQuerySet(object): continue if key == '$text_score': - # automatically set to include text scores - self._include_text_scores = True key_list.append(('_text_score', {'$meta': "textScore"})) continue diff --git a/tests/queryset/queryset.py b/tests/queryset/queryset.py index e37ab881..c91600d0 100644 --- a/tests/queryset/queryset.py +++ b/tests/queryset/queryset.py @@ -2785,15 +2785,14 @@ class QuerySetTest(unittest.TestCase): self.assertTrue('planejamento' in new.title) query = News.objects.search_text("candidata") - - self.assertTrue(query._include_text_scores) + self.assertEqual(query._search_text, "candidata") new = query.first() self.assertTrue(isinstance(new.get_text_score(), float)) # count query = News.objects.search_text('brasil').order_by('$text_score') - self.assertTrue(query._include_text_scores) + self.assertEqual(query._search_text, "brasil") self.assertEqual(query.count(), 3) self.assertEqual(query._query, {'$text': {'$search': 'brasil'}})