Skip to content

Commit c250492

Browse files
committed
Add more functionality to track entity in addition add the select method for the query
1 parent accf883 commit c250492

File tree

6 files changed

+85
-34
lines changed

6 files changed

+85
-34
lines changed

pyravendb/d_commands/database_commands.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ def put_index(self, index_name, index_def, overwrite=False):
147147
response = self._requests_handler.http_request_handler(path, "GET")
148148
if not overwrite and response.status_code != 404:
149149
raise exceptions.InvalidOperationException("Cannot put index:{0},index already exists".format(index_name))
150+
150151
data = index_def.to_json()
151152
return self._requests_handler.http_request_handler(path, "PUT", data=data).json()
152153

@@ -200,7 +201,7 @@ def update_by_index(self, index_name, query, scripted_patch=None, options=None):
200201
scripted_patch = scripted_patch.to_json()
201202

202203
response = self._requests_handler.http_request_handler(path, "EVAL", data=scripted_patch)
203-
if response.status_code != 200:
204+
if response.status_code != 200 and response.status_code != 202:
204205
raise response.raise_for_status()
205206
return response.json()
206207

@@ -217,7 +218,7 @@ def delete_by_index(self, index_name, query, options=None):
217218
"""
218219
path = Utils.build_path(index_name, query, options)
219220
response = self._requests_handler.http_request_handler(path, "DELETE")
220-
if response.status_code != 200:
221+
if response.status_code != 200 and response.status_code != 202:
221222
try:
222223
raise exceptions.ErrorResponseException(response.json()["Error"][:100])
223224
except ValueError:
@@ -270,6 +271,9 @@ def query(self, index_name, index_query, includes=None, metadata_only=False, ind
270271
if index_query.sort_fields:
271272
for field in index_query.sort_fields:
272273
path += "&sort={0}".format(field)
274+
if index_query.fetch:
275+
for item in index_query.fetch:
276+
path += "&fetch={0}".format(item)
273277
if metadata_only:
274278
path += "&metadata-only=true"
275279
if index_entries_only:

pyravendb/data/indexes.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ def __str__(self):
4040
class IndexDefinition(object):
4141
def __init__(self, index_map, name=None, **kwargs):
4242
"""
43-
@param index_maps: The map of the index
44-
:type str
43+
@param index_map: The map of the index
44+
:type str or tuple
4545
@param name: The name of the index
4646
:type str
4747
@param kwargs: Can be use to initialize the other option in the index definition
@@ -58,16 +58,14 @@ def __init__(self, index_map, name=None, **kwargs):
5858
self._is_compiled = False
5959
self.is_side_by_side_index = kwargs.get("is_side_by_side_index", False)
6060
self.is_test_index = kwargs.get("is_test_index", False)
61-
self.is_map_reduce = kwargs.get("is_map_reduce", False)
6261
self.lock_mod = kwargs.get("lock_mod", IndexLockMode.Unlock)
6362
self.max_index_outputs_per_document = kwargs.get("max_index_outputs_per_document", None)
6463
self.sort_options = kwargs.get("sort_options", {})
6564
self.spatial_indexes = kwargs.get("spatial_indexes", {})
6665
self.stores = kwargs.get("stores", {})
6766
self.suggestions = kwargs.get("suggestions", {})
6867
self.term_vectors = kwargs.get("term_vectors", {})
69-
self.maps = kwargs.get("maps", set())
70-
self.map = index_map
68+
self.maps = (index_map,) if isinstance(index_map, str) else tuple(set(index_map, ))
7169

7270
@property
7371
def type(self):
@@ -79,9 +77,15 @@ def type(self):
7977
return "MapReduce"
8078
return "Map"
8179

80+
@property
81+
def is_map_reduce(self):
82+
return True if self.reduce else False
83+
8284
@property
8385
def map(self):
84-
return list(self.maps)[0]
86+
if not isinstance(self.maps, str):
87+
return self.maps[0]
88+
return self.maps
8589

8690
@map.setter
8791
def map(self, value):
@@ -96,7 +100,7 @@ def to_json(self):
96100
"InternalFieldsMapping": self.internal_fields_mapping, "IsCompiled": self._is_compiled,
97101
"IsMapReduce": self.is_map_reduce, "IsSideBySideIndex": self.is_side_by_side_index,
98102
"IsTestIndex": self.is_test_index, "LockMode": str(self.lock_mod), "Map": self.map,
99-
"Maps": list(self.maps),
103+
"Maps": self.maps,
100104
"MaxIndexOutputsPerDocument": self.max_index_outputs_per_document, "Name": self.name,
101105
"Reduce": self.reduce, "SortOptions": {key: str(self.sort_options[key]) for key in self.sort_options},
102106
"SpatialIndexes": self.spatial_indexes,
@@ -115,6 +119,8 @@ def __init__(self, query="", total_size=0, skipped_results=0, default_operator=N
115119
:type int
116120
@param default_operator: The operator of the query (AND or OR) the default value is OR
117121
:type Enum.QueryOperator
122+
@param fetch fetch only the terms you want from the index
123+
:type list
118124
"""
119125
self.query = query
120126
self.total_size = total_size
@@ -124,6 +130,7 @@ def __init__(self, query="", total_size=0, skipped_results=0, default_operator=N
124130
self.default_operator = default_operator
125131
self.sort_hints = kwargs.get("sort_hints", {})
126132
self.sort_fields = kwargs.get("sort_fields", {})
133+
self.fetch = kwargs.get("fetch", [])
127134
self.wait_for_non_stale_results = kwargs.get("wait_for_non_stale_results", False)
128135

129136
@property

pyravendb/store/session_query.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ def __init__(self, session):
1414
self.negate = False
1515
self._sort_hints = set()
1616
self._sort_fields = set()
17+
self.fetch = None
1718

1819
def __call__(self, object_type=None, index_name=None, using_default_operator=None,
1920
wait_for_non_stale_results=False, includes=None, with_statistics=False, nested_object_types=None):
@@ -44,6 +45,17 @@ def __call__(self, object_type=None, index_name=None, using_default_operator=Non
4445
self._with_statistics = with_statistics
4546
return self
4647

48+
def select(self, *args):
49+
"""
50+
Fetch only the required fields from the server
51+
52+
@param args: The name of the terms you like to acquire
53+
54+
"""
55+
if args:
56+
self.fetch = args
57+
return self
58+
4759
def _lucene_builder(self, value, action=None):
4860
lucene_text = Utils.to_lucene(value, action=action)
4961

@@ -287,6 +299,7 @@ def _execute_query(self):
287299
response = self.session.database_commands. \
288300
query(self.index_name, IndexQuery(self.query_builder, default_operator=self.using_default_operator,
289301
sort_hints=self._sort_hints, sort_fields=self._sort_fields,
302+
fetch=self.fetch,
290303
wait_for_non_stale_results=self.wait_for_non_stale_results),
291304
includes=self.includes)
292305
if response["IsStale"] and self.wait_for_non_stale_results:
@@ -299,12 +312,15 @@ def _execute_query(self):
299312
results = []
300313
response_results = response.pop("Results")
301314
response_includes = response.pop("Includes")
315+
302316
for result in response_results:
303317
entity, metadata, original_metadata = Utils.convert_to_entity(result, self.object_type, conventions,
304-
self.nested_object_types)
305-
self.session.save_entity(key=original_metadata.get("@id", None), entity=entity,
306-
original_metadata=original_metadata,
307-
metadata=metadata, document=result)
318+
self.nested_object_types,
319+
fetch=False if not self.fetch else True)
320+
if not self.fetch:
321+
self.session.save_entity(key=original_metadata.get("@id", None), entity=entity,
322+
original_metadata=original_metadata,
323+
metadata=metadata, document=result)
308324
results.append(entity)
309325
self.session.save_includes(response_includes)
310326
if self._with_statistics:

pyravendb/tests/session_tests/query_test.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ def setUpClass(cls):
2525
cls.index_map = ("from doc in docs "
2626
"select new {"
2727
"name = doc.name,"
28-
"key = doc.key}")
29-
cls.index_sort = IndexDefinition(index_map=cls.index_map, sort_options={"key": SortOptions.float})
28+
"key = doc.key,"
29+
"doc_id = (doc.name + \" \") + doc.key}")
30+
cls.index_sort = IndexDefinition(index_map=cls.index_map, sort_options={"key": SortOptions.float},
31+
stores={"doc_id": "Yes"})
3032
cls.db.put_index("Testing_Sort", index_def=cls.index_sort, overwrite=True)
3133
cls.db.put("products/101", {"name": "test101", "key": 2, "order": "a"},
3234
{"Raven-Entity-Name": "Products", "Raven-Python-Type": "query_test.Product"})
@@ -141,3 +143,17 @@ def test_query_with_nested_object(self):
141143
session.query(object_type=Company, nested_object_types={"product": Product}).where_equals(
142144
"name", "withNesting"))
143145
self.assertTrue(isinstance(query_results[0], Company) and isinstance(query_results[0].product, Product))
146+
147+
def test_query_with_fetch_terms(self):
148+
with self.document_store.open_session() as session:
149+
query_results = list(
150+
session.query(index_name="Testing_Sort", wait_for_non_stale_results=True).where_between_or_equal
151+
("key", 2, 4).select("doc_id"))
152+
153+
found_in_all = True
154+
for result in query_results:
155+
if not hasattr(result,"doc_id"):
156+
found_in_all = False
157+
break
158+
159+
self.assertTrue(found_in_all)

pyravendb/tools/utils.py

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -89,35 +89,43 @@ def is_inherit(parent, child):
8989
return Utils.is_inherit(parent, child.__base__)
9090

9191
@staticmethod
92-
def convert_to_entity(document, object_type, conventions, nested_object_types=None):
92+
def convert_to_entity(document, object_type, conventions, nested_object_types=None, fetch=False):
9393
metadata = document.pop("@metadata")
9494
original_metadata = metadata.copy()
9595
type_from_metadata = conventions.try_get_type_from_metadata(metadata)
9696
entity = _DynamicStructure(**document)
97-
object_from_metadata = None
98-
if type_from_metadata is not None:
99-
object_from_metadata = Utils.import_class(type_from_metadata)
100-
101-
if object_from_metadata is None:
102-
if object_type is not None:
103-
entity.__class__ = object_type
104-
metadata["Raven-Python-Type"] = "{0}.{1}".format(object_type.__module__, object_type.__name__)
105-
else:
106-
if object_type and not Utils.is_inherit(object_type, object_from_metadata):
107-
raise exceptions.InvalidOperationException(
108-
"Unable to cast object of type {0} to type {1}".format(object_from_metadata, object_type))
109-
entity.__class__ = object_from_metadata
110-
# Checking the class for initialize
111-
entity_initialize_dict = Utils.make_initialize_dict(document, entity.__class__.__init__)
97+
if not fetch:
98+
object_from_metadata = None
99+
if type_from_metadata is not None:
100+
object_from_metadata = Utils.import_class(type_from_metadata)
101+
102+
if object_from_metadata is None:
103+
if object_type is not None:
104+
entity.__class__ = object_type
105+
metadata["Raven-Python-Type"] = "{0}.{1}".format(object_type.__module__, object_type.__name__)
106+
else:
107+
if object_type and not Utils.is_inherit(object_type, object_from_metadata):
108+
raise exceptions.InvalidOperationException(
109+
"Unable to cast object of type {0} to type {1}".format(object_from_metadata, object_type))
110+
entity.__class__ = object_from_metadata
111+
# Checking the class for initialize
112+
entity_initialize_dict = Utils.make_initialize_dict(document, entity.__class__.__init__)
112113

113-
entity = entity.__class__(**entity_initialize_dict)
114+
entity = entity.__class__(**entity_initialize_dict)
114115

115116
if nested_object_types:
116117
for key in nested_object_types:
117118
attr = getattr(entity, key)
118119
if attr:
119120
try:
120-
if nested_object_types[key] is datetime:
121+
if isinstance(attr, list):
122+
nested_list = []
123+
for attribute in attr:
124+
nested_list.append(nested_object_types[key](
125+
**Utils.make_initialize_dict(attribute, nested_object_types[key].__init__)))
126+
setattr(entity, key, nested_list)
127+
128+
elif nested_object_types[key] is datetime:
121129
setattr(entity, key, Utils.string_to_datetime(attr))
122130
elif nested_object_types[key] is timedelta:
123131
setattr(entity, key, Utils.string_to_timedelta(attr))

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
setup(
44
name='pyravendb',
55
packages=find_packages(),
6-
version='1.2.0',
6+
version='1.3.0',
77
description='This is the official python client for RavenDB document database',
88
author='Idan Haim Shalom',
99
author_email='[email protected]',

0 commit comments

Comments
 (0)