Skip to content

Commit 46f26ed

Browse files
committed
RDBC-780 RavenDB_16328_AnalyzersTest::canUseCustomAnalyzer
1 parent 3846d24 commit 46f26ed

File tree

4 files changed

+195
-2
lines changed

4 files changed

+195
-2
lines changed
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1-
from typing import Optional
1+
from typing import Optional, Any, Dict
22

33

44
class AnalyzerDefinition:
55
def __init__(self, name: Optional[str] = None, code: Optional[str] = None):
66
self.name = name
77
self.code = code
8+
9+
@classmethod
10+
def from_json(cls, json_dict: Dict[str, Any]) -> "AnalyzerDefinition":
11+
return cls(json_dict["Name"], json_dict["Code"])
12+
13+
def to_json(self) -> Dict[str, Any]:
14+
return {"Name": self.name, "Code": self.code}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
from typing import List, TYPE_CHECKING
2+
3+
import requests
4+
5+
from ravendb import RaftCommand, ServerNode
6+
from ravendb.documents.indexes.analysis.definitions import AnalyzerDefinition
7+
from ravendb.http.raven_command import VoidRavenCommand
8+
from ravendb.serverwide.operations.common import VoidServerOperation
9+
from ravendb.tools.utils import Utils
10+
from ravendb.util.util import RaftIdGenerator
11+
12+
if TYPE_CHECKING:
13+
from ravendb.documents.conventions import DocumentConventions
14+
15+
16+
class PutServerWideAnalyzersOperation(VoidServerOperation):
17+
def __init__(self, *analyzers_to_add: AnalyzerDefinition):
18+
if not analyzers_to_add:
19+
raise ValueError("Analyzers must not be empty or None")
20+
21+
self._analyzers_to_add = analyzers_to_add
22+
23+
def get_command(
24+
self, conventions: "DocumentConventions"
25+
) -> "PutServerWideAnalyzersOperation.PutServerWideAnalyzersCommand":
26+
return self.PutServerWideAnalyzersCommand(conventions, list(self._analyzers_to_add))
27+
28+
class PutServerWideAnalyzersCommand(VoidRavenCommand, RaftCommand):
29+
def __init__(self, conventions: "DocumentConventions", analyzers_to_add: List[AnalyzerDefinition]):
30+
if not conventions:
31+
raise ValueError("Conventions cannot be None")
32+
33+
if analyzers_to_add is None:
34+
raise ValueError("Analyzers cannot be None")
35+
36+
super().__init__()
37+
38+
self._analyzers_to_add = []
39+
for i in range(len(analyzers_to_add)):
40+
analyzer = analyzers_to_add[i]
41+
if analyzer.name is None:
42+
raise ValueError("Name cannot be None")
43+
44+
self._analyzers_to_add.append(analyzer.to_json())
45+
46+
def create_request(self, node: ServerNode) -> requests.Request:
47+
url = f"{node.url}/admin/analyzers"
48+
49+
request = requests.Request(method="PUT", url=url)
50+
request.data = {"Analyzers": self._analyzers_to_add}
51+
52+
return request
53+
54+
def is_read_request(self) -> bool:
55+
return False
56+
57+
def get_raft_unique_request_id(self) -> str:
58+
return RaftIdGenerator.new_id()
59+
60+
61+
class DeleteServerWideAnalyzerOperation(VoidServerOperation):
62+
def __init__(self, analyzer_name: str):
63+
if analyzer_name is None:
64+
raise ValueError("Analyzer name cannot be None")
65+
66+
self._analyzer_name = analyzer_name
67+
68+
def get_command(
69+
self, conventions: "DocumentConventions"
70+
) -> "DeleteServerWideAnalyzerOperation.DeleteServerWideAnalyzerCommand":
71+
return self.DeleteServerWideAnalyzerCommand(self._analyzer_name)
72+
73+
class DeleteServerWideAnalyzerCommand(VoidRavenCommand, RaftCommand):
74+
def __init__(self, analyzer_name: str):
75+
if analyzer_name is None:
76+
raise ValueError("Analyzer name cannot be None")
77+
super().__init__()
78+
79+
self._analyzer_name = analyzer_name
80+
81+
def create_request(self, node: ServerNode) -> requests.Request:
82+
return requests.Request("DELETE", f"{node.url}/admin/analyzers?name={Utils.quote_key(self._analyzer_name)}")
83+
84+
def get_raft_unique_request_id(self) -> str:
85+
return RaftIdGenerator.new_id()

ravendb/tests/jvm_migrated_tests/issues_tests/test_ravenDB_16328.py

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
import unittest
2+
from datetime import timedelta
3+
from typing import Type
24

3-
from ravendb import SorterDefinition
5+
from ravendb import SorterDefinition, AbstractIndexCreationTask, AnalyzerDefinition, DocumentStore
6+
from ravendb.documents.indexes.definitions import FieldIndexing
7+
from ravendb.documents.operations.indexes import ResetIndexOperation
48
from ravendb.infrastructure.orders import Company
9+
from ravendb.serverwide.operations.analyzers import PutServerWideAnalyzersOperation, DeleteServerWideAnalyzerOperation
510
from ravendb.serverwide.operations.sorters import PutServerWideSortersOperation, DeleteServerWideSorterOperation
611
from ravendb.tests.test_base import TestBase
712

13+
814
sorter_code = (
915
"using System;\n"
1016
"using System.Collections.Generic;\n"
@@ -96,3 +102,95 @@ def test_can_use_custom_sorter(self):
96102
@staticmethod
97103
def get_sorter(name) -> str:
98104
return sorter_code.replace("MySorter", name)
105+
106+
analyzer = (
107+
"using System.IO;\n"
108+
"using Lucene.Net.Analysis;\n"
109+
"using Lucene.Net.Analysis.Standard;\n"
110+
"\n"
111+
"namespace SlowTests.Data.RavenDB_14939\n"
112+
"{\n"
113+
" public class MyAnalyzer : StandardAnalyzer\n"
114+
" {\n"
115+
" public MyAnalyzer()\n"
116+
" : base(Lucene.Net.Util.Version.LUCENE_30)\n"
117+
" {\n"
118+
" }\n"
119+
"\n"
120+
" public override TokenStream TokenStream(string fieldName, TextReader reader)\n"
121+
" {\n"
122+
" return new ASCIIFoldingFilter(base.TokenStream(fieldName, reader));\n"
123+
" }\n"
124+
" }\n"
125+
"}\n"
126+
)
127+
128+
@staticmethod
129+
def _fill(store: DocumentStore) -> None:
130+
with store.open_session() as session:
131+
session.store(Customer(name="Rogério"))
132+
session.store(Customer(name="Rogerio"))
133+
session.store(Customer(name="Paulo Rogerio"))
134+
session.store(Customer(name="Paulo Rogério"))
135+
session.save_changes()
136+
137+
def _assert_count(
138+
self, store: DocumentStore, index: Type[AbstractIndexCreationTask], expected_count: int = 4
139+
) -> None:
140+
self.wait_for_indexing(store)
141+
142+
with store.open_session() as session:
143+
results = list(session.query_index_type(index, Customer).no_caching().search("name", "Rogério*"))
144+
self.assertEqual(expected_count, len(results))
145+
146+
def test_can_use_custom_analyzer(self):
147+
analyzer_name = "MyAnalyzer"
148+
149+
self.assertRaisesWithMessageContaining(
150+
self.store.execute_index,
151+
Exception,
152+
"Cannot find analyzer type '" + analyzer_name + "' for field: name",
153+
self.MyIndex(analyzer_name),
154+
)
155+
156+
try:
157+
analyzer_definition = AnalyzerDefinition()
158+
analyzer_definition.name = analyzer_name
159+
analyzer_definition.code = self.analyzer
160+
161+
self.store.maintenance.server.send(PutServerWideAnalyzersOperation(analyzer_definition))
162+
163+
self.store.execute_index(self.MyIndex(analyzer_name))
164+
165+
self._fill(self.store)
166+
167+
self.wait_for_indexing(self.store)
168+
169+
self._assert_count(self.store, self.MyIndex)
170+
171+
self.store.maintenance.server.send(DeleteServerWideAnalyzerOperation(analyzer_name))
172+
173+
self.store.maintenance.send(ResetIndexOperation(self.MyIndex().index_name))
174+
175+
errors = self.wait_for_indexing_errors(self.store, timedelta(seconds=10))
176+
self.assertEqual(1, len(errors))
177+
self.assertEqual(1, len(errors[0].errors))
178+
self.assertIn(
179+
"Cannot find analyzer type '" + analyzer_name + "' for field: name", errors[0].errors[0].error
180+
)
181+
finally:
182+
self.store.maintenance.server.send(DeleteServerWideAnalyzerOperation(analyzer_name))
183+
184+
class MyIndex(AbstractIndexCreationTask):
185+
def __init__(self, analyzer_name: str = "MyAnalyzer"):
186+
super().__init__()
187+
self.map = "from customer in docs.Customers select new { customer.name }"
188+
189+
self._index("name", FieldIndexing.SEARCH)
190+
self._analyze("name", analyzer_name)
191+
192+
193+
class Customer:
194+
def __init__(self, Id: str = None, name: str = None):
195+
self.Id = Id
196+
self.name = name

ravendb/tests/jvm_migrated_tests/server_tests/test_compress_all_collections.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import unittest
2+
13
from ravendb import GetDatabaseRecordOperation, DocumentsCompressionConfiguration
24
from ravendb.serverwide.operations.documents_compression import UpdateDocumentsCompressionConfigurationOperation
35
from ravendb.tests.test_base import TestBase
@@ -7,6 +9,7 @@ class TestCompressAllCollections(TestBase):
79
def setUp(self):
810
super(TestCompressAllCollections, self).setUp()
911

12+
@unittest.skip("Skipping due to license on CI/CD")
1013
def test_compress_all_collections_after_docs_change(self):
1114
# we are running in memory - just check if command will be sent to server
1215
self.store.maintenance.send(

0 commit comments

Comments
 (0)