Skip to content

Commit 47cfa26

Browse files
authored
Merge pull request #196 from poissoncorp/RDBC-766
RDBC-766 Python client - time series 3
2 parents 2fcf58e + 74f9911 commit 47cfa26

23 files changed

+1856
-75
lines changed

ravendb/documents/indexes/index_creation.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ def __init__(self, index_name: str):
155155
if len(self._index_name) > 256:
156156
raise ValueError(f"The index name is limited to 256 characters, but was: {self._index_name}")
157157

158-
self.reduce: Union[None, str] = None
158+
self.reduce: Optional[str] = None
159159

160160
self.stores_strings: Dict[str, FieldStorage] = {}
161161
self.indexes_strings: Dict[str, FieldIndexing] = {}
@@ -164,17 +164,17 @@ def __init__(self, index_name: str):
164164
self.term_vectors_strings: Dict[str, FieldTermVector] = {}
165165
self.spatial_indexes_strings: Dict[str, SpatialOptions] = {}
166166

167-
self.lock_mode: Union[None, IndexLockMode] = None
168-
self.priority: Union[None, IndexLockMode] = None
169-
self.state: Union[None, IndexState] = None
170-
self.deployment_mode: Union[None, IndexDeploymentMode] = None
167+
self.lock_mode: Optional[IndexLockMode] = None
168+
self.priority: Optional[IndexLockMode] = None
169+
self.state: Optional[IndexState] = None
170+
self.deployment_mode: Optional[IndexDeploymentMode] = None
171171

172-
self.output_reduce_to_collection: Union[None, str] = None
173-
self.pattern_for_output_reduce_to_collection_references: Union[None, str] = None
174-
self.pattern_references_collection_name: Union[None, str] = None
172+
self.output_reduce_to_collection: Optional[str] = None
173+
self.pattern_for_output_reduce_to_collection_references: Optional[str] = None
174+
self.pattern_references_collection_name: Optional[str] = None
175175

176-
self.additional_sources: Union[None, Dict[str, str]] = None
177-
self.additional_assemblies: Union[None, Set[AdditionalAssembly]] = None
176+
self.additional_sources: Optional[Dict[str, str]] = None
177+
self.additional_assemblies: Optional[Set[AdditionalAssembly]] = None
178178
self.configuration: Dict[str, str] = {}
179179

180180
@abstractmethod
Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
from abc import ABC
2+
from typing import Optional, Set, Dict, Callable, Union, TypeVar, List
3+
4+
from ravendb import IndexDefinition, IndexSourceType
5+
from ravendb.documents.conventions import DocumentConventions
6+
from ravendb.documents.indexes.definitions import (
7+
IndexPriority,
8+
IndexLockMode,
9+
IndexDeploymentMode,
10+
IndexState,
11+
FieldStorage,
12+
FieldIndexing,
13+
FieldTermVector,
14+
IndexFieldOptions,
15+
IndexType,
16+
)
17+
from ravendb.documents.indexes.index_creation import AbstractIndexCreationTaskBase, AbstractIndexDefinitionBuilder
18+
from ravendb.documents.indexes.spatial.configuration import SpatialOptions, SpatialOptionsFactory
19+
from ravendb.primitives import constants
20+
21+
22+
_T_IndexDefinition = TypeVar("_T_IndexDefinition", bound=IndexDefinition)
23+
24+
25+
class TimeSeriesIndexDefinition(IndexDefinition):
26+
@property
27+
def source_type(self) -> IndexSourceType:
28+
return IndexSourceType.TIME_SERIES
29+
30+
31+
class TimeSeriesIndexDefinitionBuilder(AbstractIndexDefinitionBuilder[TimeSeriesIndexDefinition]):
32+
def __init__(self, index_name: Optional[str] = None):
33+
super().__init__(index_name)
34+
self.map: Optional[str] = None
35+
36+
def _new_index_definition(self) -> TimeSeriesIndexDefinition:
37+
return TimeSeriesIndexDefinition()
38+
39+
def to_index_definition(
40+
self, conventions: DocumentConventions, validate_map: bool = True
41+
) -> TimeSeriesIndexDefinition:
42+
if self.map is None and validate_map:
43+
raise RuntimeError(
44+
f"Map is required to generate an index, "
45+
f"you cannot create an index without a valid Map property (in index {self._index_name})."
46+
)
47+
return super().to_index_definition(conventions, validate_map)
48+
49+
def _to_index_definition(
50+
self, index_definition: TimeSeriesIndexDefinition, conventions: DocumentConventions
51+
) -> None:
52+
if map is None:
53+
return
54+
55+
index_definition.maps.add(self.map)
56+
57+
58+
class AbstractGenericTimeSeriesIndexCreationTask(AbstractIndexCreationTaskBase[TimeSeriesIndexDefinition], ABC):
59+
def __init__(
60+
self,
61+
conventions: DocumentConventions = None,
62+
priority: IndexPriority = None,
63+
lock_mode: IndexLockMode = None,
64+
deployment_mode: IndexDeploymentMode = None,
65+
state: IndexState = None,
66+
):
67+
super().__init__(conventions, priority, lock_mode, deployment_mode, state)
68+
self._reduce: Optional[str] = None
69+
self.stores_strings: Dict[str, FieldStorage] = {}
70+
self.indexes_strings: Dict[str, FieldIndexing] = {}
71+
self.analyzers_strings: Dict[str, str] = {}
72+
self.index_suggestions: Set[str] = set()
73+
self.term_vectors_strings: Dict[str, FieldTermVector] = {}
74+
self.spatial_options_strings: Dict[str, SpatialOptions] = {}
75+
76+
self._output_reduce_to_collection: Optional[str] = None
77+
self._pattern_for_output_reduce_to_collection_references: Optional[str] = None
78+
self._pattern_references_collection_name: Optional[str] = None
79+
80+
@property
81+
def is_map_reduce(self) -> bool:
82+
return self._reduce is not None
83+
84+
def _index(self, field: str, indexing: FieldIndexing) -> None:
85+
self.indexes_strings[field] = indexing
86+
87+
def _spatial(self, field: str, indexing: Callable[[SpatialOptionsFactory], SpatialOptions]) -> None:
88+
self.spatial_options_strings[field] = indexing(SpatialOptionsFactory())
89+
90+
def _store_all_fields(self, storage: FieldStorage) -> None:
91+
self.stores_strings[constants.Documents.Indexing.Fields.ALL_FIELDS] = storage
92+
93+
def _store(self, field: str, storage: FieldStorage) -> None:
94+
self.stores_strings[field] = storage
95+
96+
def _analyze(self, field: str, analyzer: str) -> None:
97+
self.analyzers_strings[field] = analyzer
98+
99+
def _term_vector(self, field: str, term_vector: FieldTermVector) -> None:
100+
self.term_vectors_strings[field] = term_vector
101+
102+
def _suggestion(self, field: str) -> None:
103+
self.index_suggestions.add(field)
104+
105+
106+
class AbstractTimeSeriesIndexCreationTask(AbstractGenericTimeSeriesIndexCreationTask):
107+
def __init__(
108+
self,
109+
conventions: DocumentConventions = None,
110+
priority: IndexPriority = None,
111+
lock_mode: IndexLockMode = None,
112+
deployment_mode: IndexDeploymentMode = None,
113+
state: IndexState = None,
114+
):
115+
super().__init__(conventions, priority, lock_mode, deployment_mode, state)
116+
self.map: Optional[str] = None
117+
118+
def create_index_definition(self) -> Union[IndexDefinition, _T_IndexDefinition]:
119+
if self.conventions is None:
120+
self.conventions = DocumentConventions()
121+
122+
index_definition_builder = TimeSeriesIndexDefinitionBuilder(self.index_name)
123+
index_definition_builder.indexes_strings = self.indexes_strings
124+
index_definition_builder.analyzers_strings = self.analyzers_strings
125+
index_definition_builder.map = self.map
126+
index_definition_builder.reduce = self._reduce
127+
index_definition_builder.stores_strings = self.stores_strings
128+
index_definition_builder.suggestions_options = self.index_suggestions
129+
index_definition_builder.term_vector_strings = self.term_vectors_strings
130+
index_definition_builder.spatial_indexes_strings = self.spatial_options_strings
131+
index_definition_builder.output_reduce_to_collection = self._output_reduce_to_collection
132+
index_definition_builder.pattern_for_output_reduce_to_collection_references = (
133+
self._pattern_for_output_reduce_to_collection_references
134+
)
135+
index_definition_builder.pattern_references_collection_name = self._pattern_references_collection_name
136+
index_definition_builder.additional_sources = self.additional_sources
137+
index_definition_builder.additional_assemblies = self.additional_assemblies
138+
index_definition_builder.configuration = self.configuration
139+
index_definition_builder.lock_mode = self.lock_mode
140+
index_definition_builder.priority = self.priority
141+
index_definition_builder.state = self.state
142+
index_definition_builder.deployment_mode = self.deployment_mode
143+
144+
return index_definition_builder.to_index_definition(self.conventions)
145+
146+
147+
class AbstractMultiMapTimeSeriesIndexCreationTask(AbstractGenericTimeSeriesIndexCreationTask):
148+
def __init__(
149+
self,
150+
conventions: DocumentConventions = None,
151+
priority: IndexPriority = None,
152+
lock_mode: IndexLockMode = None,
153+
deployment_mode: IndexDeploymentMode = None,
154+
state: IndexState = None,
155+
):
156+
super().__init__(conventions, priority, lock_mode, deployment_mode, state)
157+
self.maps: List[str] = []
158+
159+
def _add_map(self, map: str) -> None:
160+
if map is None:
161+
raise ValueError("Map cannot be None.")
162+
self.maps.append(map)
163+
164+
def create_index_definition(self) -> Union[IndexDefinition, _T_IndexDefinition]:
165+
if self.conventions is None:
166+
self.conventions = DocumentConventions()
167+
168+
index_definition_builder = TimeSeriesIndexDefinitionBuilder(self.index_name)
169+
index_definition_builder.indexes_strings = self.indexes_strings
170+
index_definition_builder.analyzers_strings = self.analyzers_strings
171+
index_definition_builder.reduce = self._reduce
172+
index_definition_builder.stores_strings = self.stores_strings
173+
index_definition_builder.suggestions_options = self.index_suggestions
174+
index_definition_builder.term_vector_strings = self.term_vectors_strings
175+
index_definition_builder.spatial_indexes_strings = self.spatial_options_strings
176+
index_definition_builder.output_reduce_to_collection = self._output_reduce_to_collection
177+
index_definition_builder.pattern_for_output_reduce_to_collection_references = (
178+
self._pattern_for_output_reduce_to_collection_references
179+
)
180+
index_definition_builder.pattern_references_collection_name = self._pattern_references_collection_name
181+
index_definition_builder.additional_sources = self.additional_sources
182+
index_definition_builder.additional_assemblies = self.additional_assemblies
183+
index_definition_builder.configuration = self.configuration
184+
index_definition_builder.lock_mode = self.lock_mode
185+
index_definition_builder.priority = self.priority
186+
index_definition_builder.state = self.state
187+
index_definition_builder.deployment_mode = self.deployment_mode
188+
189+
index_definition = index_definition_builder.to_index_definition(self.conventions, False)
190+
index_definition.maps = set(self.maps)
191+
192+
return index_definition
193+
194+
195+
class AbstractJavaScriptTimeSeriesIndexCreationTask(AbstractIndexCreationTaskBase[TimeSeriesIndexDefinition]):
196+
def __init__(
197+
self,
198+
conventions: DocumentConventions = None,
199+
priority: IndexPriority = None,
200+
lock_mode: IndexLockMode = None,
201+
deployment_mode: IndexDeploymentMode = None,
202+
state: IndexState = None,
203+
):
204+
super().__init__(conventions, priority, lock_mode, deployment_mode, state)
205+
self._definition = TimeSeriesIndexDefinition()
206+
207+
@property
208+
def maps(self) -> Set[str]:
209+
return self._definition.maps
210+
211+
@maps.setter
212+
def maps(self, maps: Set[str]):
213+
self._definition.maps = maps
214+
215+
@property
216+
def fields(self) -> Dict[str, IndexFieldOptions]:
217+
return self._definition.fields
218+
219+
@fields.setter
220+
def fields(self, fields: Dict[str, IndexFieldOptions]):
221+
self._definition.fields = fields
222+
223+
@property
224+
def reduce(self) -> str:
225+
return self._definition.reduce
226+
227+
@reduce.setter
228+
def reduce(self, reduce: str):
229+
self._definition.reduce = reduce
230+
231+
def is_map_reduce(self) -> bool:
232+
return self.reduce is not None
233+
234+
@property
235+
def output_reduce_to_collection(self) -> str:
236+
return self._definition.output_reduce_to_collection
237+
238+
@output_reduce_to_collection.setter
239+
def output_reduce_to_collection(self, output_reduce_to_collection: str):
240+
self._definition.output_reduce_to_collection = output_reduce_to_collection
241+
242+
@property
243+
def pattern_references_collection_name(self) -> str:
244+
return self._definition.pattern_references_collection_name
245+
246+
@pattern_references_collection_name.setter
247+
def pattern_references_collection_name(self, pattern_references_collection_name: str):
248+
self._definition.pattern_references_collection_name = pattern_references_collection_name
249+
250+
@property
251+
def pattern_for_output_reduce_to_collection_references(self) -> str:
252+
return self._definition.pattern_for_output_reduce_to_collection_references
253+
254+
@pattern_for_output_reduce_to_collection_references.setter
255+
def pattern_for_output_reduce_to_collection_references(self, pattern_for_output_reduce_to_collection_references):
256+
self._definition.pattern_for_output_reduce_to_collection_references = (
257+
pattern_for_output_reduce_to_collection_references
258+
)
259+
260+
def create_index_definition(self) -> TimeSeriesIndexDefinition:
261+
self._definition.name = self.index_name
262+
self._definition.type = IndexType.JAVA_SCRIPT_MAP_REDUCE if self.is_map_reduce() else IndexType.JAVA_SCRIPT_MAP
263+
self._definition.additional_sources = self.additional_sources or {}
264+
self._definition.additional_assemblies = self.additional_assemblies or set()
265+
self._definition.configuration = self.configuration
266+
self._definition.lock_mode = self.lock_mode
267+
self._definition.priority = self.priority
268+
self._definition.state = self.state
269+
self._definition.deployment_mode = self.deployment_mode
270+
return self._definition

ravendb/documents/operations/indexes.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22
import enum
33
import json
4-
from typing import List, TYPE_CHECKING
4+
from typing import List, TYPE_CHECKING, Optional
55

66
import requests
77

@@ -556,7 +556,7 @@ def get_raft_unique_request_id(self) -> str:
556556

557557

558558
class GetTermsOperation(MaintenanceOperation[List[str]]):
559-
def __init__(self, index_name: str, field: str, from_value: str, page_size: int = None):
559+
def __init__(self, index_name: str, field: str, from_value: Optional[str], page_size: int = None):
560560
if index_name is None:
561561
raise ValueError("Index name cannot be None")
562562
if field is None:
@@ -584,8 +584,8 @@ def create_request(self, server_node) -> requests.Request:
584584
f"{server_node.url}/databases/{server_node.database}"
585585
f"/indexes/terms?name={Utils.escape(self.__index_name, False, False)}"
586586
f"&field={Utils.escape(self.__field, False, False)}"
587-
f"&fromValue={self.__from_value if self.__from_value is not None else ''}"
588-
f"&pageSize={self.__page_size if self.__page_size is not None else ''}",
587+
f"&fromValue={self.__from_value or ''}"
588+
f"&pageSize={self.__page_size or ''}",
589589
)
590590

591591
def set_response(self, response: str, from_cache: bool) -> None:

0 commit comments

Comments
 (0)