atomicshop 2.7.4__py3-none-any.whl → 2.7.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of atomicshop might be problematic. Click here for more details.
- atomicshop/__init__.py +1 -1
- atomicshop/filesystem.py +19 -0
- atomicshop/uuids.py +45 -0
- atomicshop/wrappers/elasticsearchw/elasticsearchw.py +68 -6
- atomicshop/wrappers/elasticsearchw/queries/__init__.py +1 -0
- atomicshop/wrappers/elasticsearchw/queries/aggregation.py +45 -0
- atomicshop/wrappers/elasticsearchw/queries/info.py +58 -0
- atomicshop/wrappers/elasticsearchw/queries/pagination.py +18 -0
- atomicshop/wrappers/elasticsearchw/queries/query_multi.py +40 -0
- atomicshop/wrappers/elasticsearchw/queries/query_single.py +87 -0
- atomicshop/wrappers/elasticsearchw/queries/size.py +12 -0
- atomicshop/wrappers/elasticsearchw/queries/sort.py +46 -0
- {atomicshop-2.7.4.dist-info → atomicshop-2.7.6.dist-info}/METADATA +1 -1
- {atomicshop-2.7.4.dist-info → atomicshop-2.7.6.dist-info}/RECORD +17 -9
- atomicshop/wrappers/elasticsearchw/queries.py +0 -149
- {atomicshop-2.7.4.dist-info → atomicshop-2.7.6.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.7.4.dist-info → atomicshop-2.7.6.dist-info}/WHEEL +0 -0
- {atomicshop-2.7.4.dist-info → atomicshop-2.7.6.dist-info}/top_level.txt +0 -0
atomicshop/__init__.py
CHANGED
atomicshop/filesystem.py
CHANGED
|
@@ -871,3 +871,22 @@ def convert_windows_to_linux_path(
|
|
|
871
871
|
linux_path = windows_path_obj.as_posix()
|
|
872
872
|
|
|
873
873
|
return str(linux_path)
|
|
874
|
+
|
|
875
|
+
|
|
876
|
+
def get_directory_size(directory_path: str):
|
|
877
|
+
"""
|
|
878
|
+
The function returns the size of the directory in bytes.
|
|
879
|
+
This is one of the fastest ways to get the size of a directory.
|
|
880
|
+
|
|
881
|
+
:param directory_path:
|
|
882
|
+
:return:
|
|
883
|
+
"""
|
|
884
|
+
|
|
885
|
+
total_size = 0
|
|
886
|
+
with os.scandir(directory_path) as it:
|
|
887
|
+
for entry in it:
|
|
888
|
+
if entry.is_file():
|
|
889
|
+
total_size += entry.stat().st_size
|
|
890
|
+
elif entry.is_dir():
|
|
891
|
+
total_size += get_directory_size(entry.path)
|
|
892
|
+
return total_size
|
atomicshop/uuids.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Choosing Between UUID Versions
|
|
6
|
+
UUID1: Use it if you need to trace back the machine that generated the UUID.
|
|
7
|
+
UUID4: Use it for almost everything else, where you need a unique ID without any other implications.
|
|
8
|
+
UUID3 and UUID5: Use them if you need consistent UUIDs generated from the same namespace and name.
|
|
9
|
+
|
|
10
|
+
Most of the time, uuid4() is preferred due to its simplicity and randomness,
|
|
11
|
+
ensuring a very low probability of ID collision without depending on the machine's identity or the exact timestamp.
|
|
12
|
+
|
|
13
|
+
Collisions:
|
|
14
|
+
The number of random version-4 UUIDs which need to be generated in order to have a 50% probability of at least
|
|
15
|
+
one collision is 2.71 quintillion. This number is equivalent to generating 1 billion UUIDs per second for about
|
|
16
|
+
85 years. The probability of one collision would be approximately 50% if every person on earth owns 600 million UUIDs.
|
|
17
|
+
https://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def generate_uuid4_random(convert_to_hex: bool = True) -> str:
|
|
22
|
+
"""
|
|
23
|
+
Generate a random UUID4.
|
|
24
|
+
|
|
25
|
+
The hex attribute of a UUID object in Python returns the hexadecimal representation of the UUID as a
|
|
26
|
+
string of 32 hexadecimal digits. This is a more compact form compared to the standard string representation
|
|
27
|
+
returned by str(uuid.uuid4()), which includes hyphens.
|
|
28
|
+
|
|
29
|
+
Here's a comparison:
|
|
30
|
+
With Hyphens (Default String Representation): The default string representation of a UUID includes hyphens,
|
|
31
|
+
separating it into five groups, such as 12345678-1234-5678-1234-567812345678.
|
|
32
|
+
This format is easy to read and is often used in textual representations where readability is a concern.
|
|
33
|
+
|
|
34
|
+
Hexadecimal (Compact Representation): The hex attribute removes the hyphens and returns the UUID as a continuous
|
|
35
|
+
string of 32 hexadecimal characters, like 12345678123456781234567812345678.
|
|
36
|
+
This compact form might be preferred when you need a shorter version of the UUID for systems that
|
|
37
|
+
don't accept hyphens or when saving space is a priority.
|
|
38
|
+
|
|
39
|
+
:return:
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
if convert_to_hex:
|
|
43
|
+
return uuid.uuid4().hex
|
|
44
|
+
else:
|
|
45
|
+
return str(uuid.uuid4())
|
|
@@ -59,6 +59,28 @@ def test_connection(elastic_wrapper: Elasticsearch = None):
|
|
|
59
59
|
return False
|
|
60
60
|
|
|
61
61
|
|
|
62
|
+
def get_stats_db_size(elastic_wrapper: Elasticsearch = None):
|
|
63
|
+
"""
|
|
64
|
+
The function returns the size of the Elasticsearch database.
|
|
65
|
+
|
|
66
|
+
:param elastic_wrapper: Elasticsearch, the Elasticsearch wrapper.
|
|
67
|
+
:return: int, the size of the Elasticsearch database in bytes.
|
|
68
|
+
|
|
69
|
+
Usage:
|
|
70
|
+
res = get_stats_db_size()
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
if elastic_wrapper is None:
|
|
74
|
+
elastic_wrapper = get_elastic_wrapper()
|
|
75
|
+
|
|
76
|
+
# Get stats for all indices
|
|
77
|
+
stats = elastic_wrapper.indices.stats()
|
|
78
|
+
|
|
79
|
+
total_size_in_bytes = stats['_all']['total']['store']['size_in_bytes']
|
|
80
|
+
|
|
81
|
+
return total_size_in_bytes
|
|
82
|
+
|
|
83
|
+
|
|
62
84
|
def index(
|
|
63
85
|
index_name: str,
|
|
64
86
|
doc: dict,
|
|
@@ -101,14 +123,17 @@ def index(
|
|
|
101
123
|
return res
|
|
102
124
|
|
|
103
125
|
|
|
104
|
-
def search(
|
|
126
|
+
def search(
|
|
127
|
+
index_name: str,
|
|
128
|
+
query: dict,
|
|
129
|
+
elastic_wrapper: Elasticsearch = None,
|
|
130
|
+
):
|
|
105
131
|
"""
|
|
106
132
|
The function searches for documents in the Elasticsearch server.
|
|
107
133
|
|
|
108
134
|
:param index_name: str, the name of the index.
|
|
109
135
|
:param query: dict, the query to be used for searching the documents.
|
|
110
136
|
:param elastic_wrapper: Elasticsearch, the Elasticsearch wrapper.
|
|
111
|
-
:param get_hits_only: bool, if True, only the hits are returned.
|
|
112
137
|
:return: dict, the result of the search operation.
|
|
113
138
|
|
|
114
139
|
Usage:
|
|
@@ -125,10 +150,13 @@ def search(index_name: str, query: dict, elastic_wrapper: Elasticsearch = None,
|
|
|
125
150
|
|
|
126
151
|
res = elastic_wrapper.search(index=index_name, body=query)
|
|
127
152
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
153
|
+
hits_only: list = get_response_hits(res)
|
|
154
|
+
|
|
155
|
+
aggregations: dict = dict()
|
|
156
|
+
if 'aggregations' in res:
|
|
157
|
+
aggregations: dict = get_all_aggregation_hits(res)
|
|
158
|
+
|
|
159
|
+
return res, hits_only, aggregations
|
|
132
160
|
|
|
133
161
|
|
|
134
162
|
def count(index_name: str, query: dict, elastic_wrapper: Elasticsearch = None):
|
|
@@ -169,3 +197,37 @@ def get_response_hits(response: dict):
|
|
|
169
197
|
"""
|
|
170
198
|
|
|
171
199
|
return [hit['_source'] for hit in response['hits']['hits']]
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def get_specific_aggregation_hits(response: dict, aggregation_name: str):
|
|
203
|
+
"""
|
|
204
|
+
The function returns the hits of an aggregation from the response.
|
|
205
|
+
|
|
206
|
+
:param response: dict, the response from the Elasticsearch server.
|
|
207
|
+
:param aggregation_name: str, the name of the aggregation.
|
|
208
|
+
:return: list, the hits of the aggregation from the response.
|
|
209
|
+
|
|
210
|
+
Usage:
|
|
211
|
+
res = get_aggregation_hits(response, aggregation_name)
|
|
212
|
+
"""
|
|
213
|
+
|
|
214
|
+
return [bucket['key'] for bucket in response['aggregations'][aggregation_name]['buckets']]
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def get_all_aggregation_hits(response: dict):
|
|
218
|
+
"""
|
|
219
|
+
The function returns all the hits of all the aggregations from the response.
|
|
220
|
+
|
|
221
|
+
:param response: dict, the response from the Elasticsearch server.
|
|
222
|
+
:return: dict, the hits of all the aggregations from the response.
|
|
223
|
+
|
|
224
|
+
Usage:
|
|
225
|
+
res = get_all_aggregation_hits(response)
|
|
226
|
+
"""
|
|
227
|
+
|
|
228
|
+
all_aggregations = {}
|
|
229
|
+
|
|
230
|
+
for agg_name, agg_content in response['aggregations'].items():
|
|
231
|
+
all_aggregations[agg_name] = [bucket['key'] for bucket in agg_content['buckets']]
|
|
232
|
+
|
|
233
|
+
return all_aggregations
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from . import aggregation, pagination, query_multi, query_single, size, sort
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
def get_unique_values(field_name: str, aggregation_name: str, size: int = 10):
|
|
2
|
+
"""
|
|
3
|
+
Create an aggregation query for Elasticsearch to get the unique values of a field.
|
|
4
|
+
This query will return the unique values of the field 'field_name'.
|
|
5
|
+
|
|
6
|
+
:param field_name: str, the name of the field to get the unique values of.
|
|
7
|
+
:param aggregation_name: str, the name of the aggregation.
|
|
8
|
+
If you want to get the aggregation hits, you will do it by this aggregation name.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
Example:
|
|
13
|
+
aggregation_name = 'unique_vendors'
|
|
14
|
+
|
|
15
|
+
body = {
|
|
16
|
+
"size": 0, # We don't need the actual documents, just the aggregation
|
|
17
|
+
"aggs": {
|
|
18
|
+
aggregation_name: {
|
|
19
|
+
"terms": {
|
|
20
|
+
"field": f"{field_name}.keyword",
|
|
21
|
+
"size": size
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
res = es.search(index=index_name, body=body)
|
|
28
|
+
unique_vendors = [bucket['key'] for bucket in res['aggregations'][aggregation_name]['buckets']]
|
|
29
|
+
:param size: int, the maximum number of unique values to return.
|
|
30
|
+
:return: dict, the aggregation query.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
"size": 0, # We don't need the actual documents, just the aggregation
|
|
35
|
+
"aggs": {
|
|
36
|
+
aggregation_name: {
|
|
37
|
+
"terms": {
|
|
38
|
+
# When doing the aggregation on a text field, we need to use the '.keyword' version of the field.
|
|
39
|
+
"field": f"{field_name}.keyword",
|
|
40
|
+
# The default terms aggregation size is 10 in elastic. If you need more, specify it.
|
|
41
|
+
"size": size
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Query types:
|
|
3
|
+
|
|
4
|
+
Term Query
|
|
5
|
+
Usage: The term query is used for exact matches. It looks for the exact term in the inverted index and doesn’t analyze the query string. This is useful for searching on fields that are exact values (like IDs, tags, etc.).
|
|
6
|
+
Example: If your field value is "Quick Brown Fox" and you search with a term query for "quick" or "Quick", it will not match because it looks for the exact term in the field.
|
|
7
|
+
|
|
8
|
+
Match Query
|
|
9
|
+
Usage: The match query is more flexible. It analyzes the query string before executing the search. This means it will consider things like tokenization and stemming. It’s suitable for full-text search.
|
|
10
|
+
Example: Using the match query for "quick" or "Quick" on the field with "Quick Brown Fox" will likely return a match because it analyzes and tokenizes the string.
|
|
11
|
+
|
|
12
|
+
Match Phrase Query
|
|
13
|
+
Usage: The match_phrase query is like the match query but it also takes the order of the words into account. It is used when you want to find exact phrases or words in a specific order.
|
|
14
|
+
Example: If you search for "Quick Brown" with a match_phrase query on a field with the value "The Quick Brown Fox", it will match. However, searching for "Brown Quick" won't match.
|
|
15
|
+
|
|
16
|
+
Additional Query Types
|
|
17
|
+
Bool Query: This allows you to combine multiple queries using boolean logic (like must, should, must_not).
|
|
18
|
+
Range Query: Useful for finding numbers or dates in a given range.
|
|
19
|
+
Wildcard Query: For searches with wildcards, useful when the exact value is partially known.
|
|
20
|
+
Prefix Query: Finds documents containing terms that start with the specified prefix.
|
|
21
|
+
Fuzzy Query: Useful for dealing with typos and spelling variations.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
AND OR:
|
|
27
|
+
"must" is AND
|
|
28
|
+
"should" is OR
|
|
29
|
+
"must_not" is NOT
|
|
30
|
+
|
|
31
|
+
Example with AND and OR:
|
|
32
|
+
You want to find all files with file_path = "/home/test1/test2/final_archive.zip" and
|
|
33
|
+
file_path = "test4.zip" or file_path = "_test4.zip"
|
|
34
|
+
Meaning you want to find all files with file_path = "/home/test1/test2/final_archive.zip/test4.zip" or
|
|
35
|
+
file_path = "/home/test1/test2/final_archive.zip/_test4.zip"
|
|
36
|
+
Since your file can be both "test4.zip" and "_test4.zip" at the same time, you need to use AND and OR.
|
|
37
|
+
|
|
38
|
+
query = {
|
|
39
|
+
"query": {
|
|
40
|
+
"bool": {
|
|
41
|
+
"must": [
|
|
42
|
+
{"match_phrase": {"file_path": "/home/test1/test2/final_archive.zip"}},
|
|
43
|
+
{
|
|
44
|
+
"bool": {
|
|
45
|
+
"should": [
|
|
46
|
+
{"match_phrase": {"file_path": "test4.zip"}},
|
|
47
|
+
{"match_phrase": {"file_path": "_test4.zip"}}
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
This is similar to Kibana KQL:
|
|
57
|
+
file_path : "/home/test1/test2/final_archive.zip" and (file_path : "test4.zip") or (file_path : "_test4.zip")
|
|
58
|
+
"""
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
def pagination(page: int, size: int) -> dict:
|
|
2
|
+
"""
|
|
3
|
+
Create the pagination query for Elasticsearch.
|
|
4
|
+
|
|
5
|
+
:param page: int, the page number.
|
|
6
|
+
:param size: int, the number of results per page.
|
|
7
|
+
:return: dict, the pagination query.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# Calculate the "from" parameter for Elasticsearch
|
|
11
|
+
start_from = (page - 1) * size
|
|
12
|
+
# Add the pagination to the query.
|
|
13
|
+
pagination_dict: dict = {
|
|
14
|
+
"from": start_from,
|
|
15
|
+
"size": size
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return pagination_dict
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
def match_and_booleans(search_terms: dict) -> dict:
|
|
2
|
+
"""
|
|
3
|
+
Generates an Elasticsearch query based on the provided search terms.
|
|
4
|
+
|
|
5
|
+
:param search_terms: A dictionary of field names and their corresponding search values.
|
|
6
|
+
:return: A dictionary representing the Elasticsearch query.
|
|
7
|
+
|
|
8
|
+
Usage for strings:
|
|
9
|
+
search_terms = {
|
|
10
|
+
"field_name1": "search_term1",
|
|
11
|
+
"field_name2": "search_term2"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
Usage for strings and booleans:
|
|
15
|
+
search_terms = {
|
|
16
|
+
"field_name1": "search_term1",
|
|
17
|
+
"field_name2": True
|
|
18
|
+
}
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
must_clauses = []
|
|
22
|
+
for field, value in search_terms.items():
|
|
23
|
+
if isinstance(value, bool):
|
|
24
|
+
# Use term query for boolean values
|
|
25
|
+
must_clauses.append({"term": {field: value}})
|
|
26
|
+
else:
|
|
27
|
+
# Use match query for text and other types
|
|
28
|
+
must_clauses.append({"match": {field: value}})
|
|
29
|
+
|
|
30
|
+
# must_clauses = [{"term": {field: value}} for field, value in search_terms.items()]
|
|
31
|
+
|
|
32
|
+
query = {
|
|
33
|
+
"query": {
|
|
34
|
+
"bool": {
|
|
35
|
+
"must": must_clauses
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return query
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
def match_all():
|
|
2
|
+
"""
|
|
3
|
+
Create a match_all query for Elasticsearch.
|
|
4
|
+
This query will match all the documents in the index.
|
|
5
|
+
|
|
6
|
+
:return: dict, the match_all query.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
"query": {
|
|
11
|
+
"match_all": {}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def match(field_name: str, search_term: str):
|
|
17
|
+
"""
|
|
18
|
+
Create a match query for Elasticsearch.
|
|
19
|
+
This query will match the documents that have the field 'field_name' set to 'search_term'.
|
|
20
|
+
|
|
21
|
+
:param field_name: str, the name of the field to search in.
|
|
22
|
+
:param search_term: str, the search term.
|
|
23
|
+
:return: dict, the match query.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
"query": {
|
|
28
|
+
"match": {
|
|
29
|
+
field_name: search_term
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def boolean_filter(field_name: str, value: bool):
|
|
36
|
+
"""
|
|
37
|
+
Create a boolean filter for Elasticsearch.
|
|
38
|
+
This filter will filter all the documents that have the field 'field_name' set to True.
|
|
39
|
+
|
|
40
|
+
:param field_name: str, the name of the field to filter by.
|
|
41
|
+
:param value: bool, the value of the field to filter by.
|
|
42
|
+
:return: dict, the boolean filter.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
"query": {
|
|
47
|
+
"bool": {
|
|
48
|
+
"filter": [
|
|
49
|
+
{"term": {field_name: value}}
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def wildcard(field_name: str, search_term: str, exact_term: bool = False):
|
|
57
|
+
"""
|
|
58
|
+
Create a wildcard query for Elasticsearch.
|
|
59
|
+
This query uses the regular 'field_name' and not the '.keyword' version.
|
|
60
|
+
What this means:
|
|
61
|
+
By default, all the text fields will be processed by the standard analyzer.
|
|
62
|
+
https://www.elastic.co/guide/en/elasticsearch/reference/current/analyzer.html
|
|
63
|
+
https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-standard-analyzer.html
|
|
64
|
+
This means that the text will be lower-cased, and the special characters will be stripped.
|
|
65
|
+
|
|
66
|
+
Example: "TEst1-TeSt2" will be processed to ["test1", "test2"].
|
|
67
|
+
|
|
68
|
+
To skip using the standard analyzer, we can use the '.keyword' version of the field or set the 'exact_term' to True.
|
|
69
|
+
|
|
70
|
+
:param field_name: str, the name of the field to search in.
|
|
71
|
+
:param search_term: str, the search term with the wildcard '*'.
|
|
72
|
+
:param exact_term: bool, if True, the '.keyword' version of the field will be used.
|
|
73
|
+
:return: dict, the wildcard query.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
if exact_term:
|
|
77
|
+
field_name = f"{field_name}.keyword"
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
"query": {
|
|
81
|
+
"wildcard": {
|
|
82
|
+
field_name: {
|
|
83
|
+
"value": search_term
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
def maximum():
|
|
2
|
+
"""
|
|
3
|
+
Add the maximum size to the query.
|
|
4
|
+
The maximum size is 10000 for regular queries.
|
|
5
|
+
If you need more than 10000 results, you need to use the 'scroll' API or Search After.
|
|
6
|
+
|
|
7
|
+
:return: dict, the query with the maximum size.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
"size": 10000
|
|
12
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
def ascending(field_name: str):
|
|
2
|
+
"""
|
|
3
|
+
Create a sorting query for Elasticsearch.
|
|
4
|
+
This query will sort the results by the 'field_name' field in ascending order.
|
|
5
|
+
|
|
6
|
+
:param field_name: str, the name of the field to sort by.
|
|
7
|
+
:return: dict, the sorting query.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
"sort": [
|
|
12
|
+
{field_name: {"order": "asc"}}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def descending(field_name: str):
|
|
18
|
+
"""
|
|
19
|
+
Create a sorting query for Elasticsearch.
|
|
20
|
+
This query will sort the results by the 'field_name' field in descending order.
|
|
21
|
+
|
|
22
|
+
:param field_name: str, the name of the field to sort by.
|
|
23
|
+
:return: dict, the sorting query.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
"sort": [
|
|
28
|
+
{field_name: {"order": "desc"}}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def latest_time(time_field_name: str = None):
|
|
34
|
+
"""
|
|
35
|
+
Create a sorting query for Elasticsearch.
|
|
36
|
+
This query will sort the results by the 'time_field_name' field in descending order.
|
|
37
|
+
|
|
38
|
+
:param time_field_name: str, the name of the field to sort by.
|
|
39
|
+
If None, the 'timestamp' field name will be used.
|
|
40
|
+
:return: dict, the sorting query.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
if time_field_name is None:
|
|
44
|
+
time_field_name = "timestamp"
|
|
45
|
+
|
|
46
|
+
return descending(field_name=time_field_name)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
atomicshop/__init__.py,sha256=
|
|
1
|
+
atomicshop/__init__.py,sha256=DoGkKi75FQlqIpSnJTBu70jSyzfi3tC2S62u0x9o08M,122
|
|
2
2
|
atomicshop/_basics_temp.py,sha256=6cu2dd6r2dLrd1BRNcVDKTHlsHs_26Gpw8QS6v32lQ0,3699
|
|
3
3
|
atomicshop/_patch_import.py,sha256=ENp55sKVJ0e6-4lBvZnpz9PQCt3Otbur7F6aXDlyje4,6334
|
|
4
4
|
atomicshop/appointment_management.py,sha256=N3wVGJgrqJfsj_lqiRfaL3FxMEe57by5Stzanh189mk,7263
|
|
@@ -13,7 +13,7 @@ atomicshop/dns.py,sha256=bNZOo5jVPzq7OT2qCPukXoK3zb1oOsyaelUwQEyK1SA,2500
|
|
|
13
13
|
atomicshop/domains.py,sha256=Rxu6JhhMqFZRcoFs69IoEd1PtYca0lMCG6F1AomP7z4,3197
|
|
14
14
|
atomicshop/emails.py,sha256=I0KyODQpIMEsNRi9YWSOL8EUPBiWyon3HRdIuSj3AEU,1410
|
|
15
15
|
atomicshop/file_types.py,sha256=-0jzQMRlmU1AP9DARjk-HJm1tVE22E6ngP2mRblyEjY,763
|
|
16
|
-
atomicshop/filesystem.py,sha256=
|
|
16
|
+
atomicshop/filesystem.py,sha256=b9FJjw2IoZNd-U7feY5o9y9w58vBgGHAgsahxlkzhbA,33163
|
|
17
17
|
atomicshop/functions.py,sha256=pK8hoCE9z61PtWCxQJsda7YAphrLH1wxU5x-1QJP-sY,499
|
|
18
18
|
atomicshop/hashing.py,sha256=Le8qGFyt3_wX-zGTeQShz7L2HL_b6nVv9PnawjglyHo,3474
|
|
19
19
|
atomicshop/http_parse.py,sha256=nrf2rZcprLqtW8HVrV7TCZ1iTBcWRRy-mXIlAOzcaJs,9703
|
|
@@ -40,6 +40,7 @@ atomicshop/system_resources.py,sha256=CMJfhDv6dI9K3IejpyKu-6qRlfeTphaOCd2RaLxXDy
|
|
|
40
40
|
atomicshop/tempfiles.py,sha256=uq1ve2WlWehZ3NOTXJnpBBMt6HyCdBufqedF0HyzA6k,2517
|
|
41
41
|
atomicshop/timer.py,sha256=KxBBgVM8po6pUJDW8TgY1UXj0iiDmRmL5XDCq0VHAfU,1670
|
|
42
42
|
atomicshop/urls.py,sha256=CQl1j1kjEVDlAuYJqYD9XxPF1SUSgrmG8PjlcXNEKsQ,597
|
|
43
|
+
atomicshop/uuids.py,sha256=JSQdm3ZTJiwPQ1gYe6kU0TKS_7suwVrHc8JZDGYlydM,2214
|
|
43
44
|
atomicshop/virtualization.py,sha256=LPP4vjE0Vr10R6DA4lqhfX_WaNdDGRAZUW0Am6VeGco,494
|
|
44
45
|
atomicshop/web.py,sha256=K3UndqJqHO9bTogZUWDz-IEZN776KNhpk28m3Ct_pbc,11069
|
|
45
46
|
atomicshop/addons/PlayWrightCodegen.cmd,sha256=Z5cnllsyXD4F1W2h-WLEnyFkg5nZy0-hTGHRWXVOuW4,173
|
|
@@ -154,8 +155,15 @@ atomicshop/wrappers/dockerw/dockerw.py,sha256=w8zSJr5C7cbvbuG09ORCpAe0BOcibqqL_Z
|
|
|
154
155
|
atomicshop/wrappers/dockerw/install_docker.py,sha256=dpSOmD690oLukoLCo0u6Pzh5fRyCWBuSQEtG8VwC3jk,2765
|
|
155
156
|
atomicshop/wrappers/elasticsearchw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
156
157
|
atomicshop/wrappers/elasticsearchw/config_basic.py,sha256=nMtWYBlkQwzUMTLBaL3US8-f87bNPS_wzVxpLR1D6Hc,121
|
|
157
|
-
atomicshop/wrappers/elasticsearchw/elasticsearchw.py,sha256=
|
|
158
|
-
atomicshop/wrappers/elasticsearchw/queries.py,sha256=
|
|
158
|
+
atomicshop/wrappers/elasticsearchw/elasticsearchw.py,sha256=KCU1OgzqG4YALQkVZqF6tpsCG-gU_SkJa1HQK6zV07A,7301
|
|
159
|
+
atomicshop/wrappers/elasticsearchw/queries/__init__.py,sha256=KBjT-bAt75CJsx1Apko9mpuFU4pfZV8DcGWQvpX65RU,78
|
|
160
|
+
atomicshop/wrappers/elasticsearchw/queries/aggregation.py,sha256=N9a5yMMnb10sMa_x1qJBFQpgyJ49UWo8_vxuqmUtZ1A,1742
|
|
161
|
+
atomicshop/wrappers/elasticsearchw/queries/info.py,sha256=e2O_vW8admhs5-kyoSGkZYHGK2O-hfdAOsWuMZzY0D4,2821
|
|
162
|
+
atomicshop/wrappers/elasticsearchw/queries/pagination.py,sha256=ySPJuXZOMiNAo7SDycxVOg35uP-CK59GzrLbs-0CqcM,509
|
|
163
|
+
atomicshop/wrappers/elasticsearchw/queries/query_multi.py,sha256=hiqLqX3_Go_QKZpcyEXr9Qvyxf6uKHP3IS6JSNzChL4,1167
|
|
164
|
+
atomicshop/wrappers/elasticsearchw/queries/query_single.py,sha256=HdYBW17vIvmHTI3nviOBmMspefDCT4xWXXnK7cbE2gQ,2662
|
|
165
|
+
atomicshop/wrappers/elasticsearchw/queries/size.py,sha256=ZThvspfxpXRBI6Mht9kkb5lO-9KtprXqll_jBxDggns,319
|
|
166
|
+
atomicshop/wrappers/elasticsearchw/queries/sort.py,sha256=-CUhgcs_AVRvncRlLTl5IJZE8K3RgDNLYSIHnn0j7aE,1274
|
|
159
167
|
atomicshop/wrappers/factw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
160
168
|
atomicshop/wrappers/factw/config_fact.py,sha256=J-K9Zn50WcDC7ubb-boraSZExfBk7a6M52NhRJVlsjk,895
|
|
161
169
|
atomicshop/wrappers/factw/config_install.py,sha256=QRygFnZ5r1ybJQl7ftFci3kNRmU-a-w3lMG1joElvcY,417
|
|
@@ -214,8 +222,8 @@ atomicshop/wrappers/socketw/socket_server_tester.py,sha256=AhpurHJmP2kgzHaUbq5ey
|
|
|
214
222
|
atomicshop/wrappers/socketw/socket_wrapper.py,sha256=aXBwlEIJhFT0-c4i8iNlFx2It9VpCEpsv--5Oqcpxao,11624
|
|
215
223
|
atomicshop/wrappers/socketw/ssl_base.py,sha256=k4V3gwkbq10MvOH4btU4onLX2GNOsSfUAdcHmL1rpVE,2274
|
|
216
224
|
atomicshop/wrappers/socketw/statistics_csv.py,sha256=t3dtDEfN47CfYVi0CW6Kc2QHTEeZVyYhc57IYYh5nmA,826
|
|
217
|
-
atomicshop-2.7.
|
|
218
|
-
atomicshop-2.7.
|
|
219
|
-
atomicshop-2.7.
|
|
220
|
-
atomicshop-2.7.
|
|
221
|
-
atomicshop-2.7.
|
|
225
|
+
atomicshop-2.7.6.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
|
|
226
|
+
atomicshop-2.7.6.dist-info/METADATA,sha256=ouPceXaGo8HF2r-OEYqADM0a2mpeM_V7zvxoLrqJTwE,10369
|
|
227
|
+
atomicshop-2.7.6.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
228
|
+
atomicshop-2.7.6.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
|
|
229
|
+
atomicshop-2.7.6.dist-info/RECORD,,
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
def create_match_all():
|
|
2
|
-
"""
|
|
3
|
-
Create a match_all query for Elasticsearch.
|
|
4
|
-
This query will match all the documents in the index.
|
|
5
|
-
|
|
6
|
-
:return: dict, the match_all query.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
return {
|
|
10
|
-
"query": {
|
|
11
|
-
"match_all": {}
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def create_boolean_filter(field_name: str, value: bool):
|
|
17
|
-
"""
|
|
18
|
-
Create a boolean filter for Elasticsearch.
|
|
19
|
-
This filter will filter all the documents that have the field 'field_name' set to True.
|
|
20
|
-
|
|
21
|
-
:param field_name: str, the name of the field to filter by.
|
|
22
|
-
:param value: bool, the value of the field to filter by.
|
|
23
|
-
:return: dict, the boolean filter.
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
"query": {
|
|
28
|
-
"bool": {
|
|
29
|
-
"filter": [
|
|
30
|
-
{"term": {field_name: value}}
|
|
31
|
-
]
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def create_wildcard(field_name: str, search_term: str):
|
|
38
|
-
"""
|
|
39
|
-
Create a wildcard query for Elasticsearch.
|
|
40
|
-
This query uses the regular 'field_name' and not the '.keyword' version.
|
|
41
|
-
What this means:
|
|
42
|
-
By default, all the text fields will be processed by the standard analyzer.
|
|
43
|
-
https://www.elastic.co/guide/en/elasticsearch/reference/current/analyzer.html
|
|
44
|
-
https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-standard-analyzer.html
|
|
45
|
-
This means that the text will be lower-cased, and the special characters will be stripped.
|
|
46
|
-
|
|
47
|
-
Example: "TEst1-TeSt2" will be processed to ["test1", "test2"].
|
|
48
|
-
|
|
49
|
-
To skip using the standard analyzer, we can use the '.keyword' version of the field.
|
|
50
|
-
|
|
51
|
-
:param field_name: str, the name of the field to search in.
|
|
52
|
-
:param search_term: str, the search term with the wildcard '*'.
|
|
53
|
-
:return: dict, the wildcard query.
|
|
54
|
-
"""
|
|
55
|
-
|
|
56
|
-
return {
|
|
57
|
-
"query": {
|
|
58
|
-
"wildcard": {
|
|
59
|
-
field_name: {
|
|
60
|
-
"value": search_term
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def create_wildcard_exact_term(field_name: str, search_term: str):
|
|
68
|
-
"""
|
|
69
|
-
Create a wildcard query for Elasticsearch to unprocessed version by the standard analyzer.
|
|
70
|
-
This query uses the '.keyword' version of the field.
|
|
71
|
-
|
|
72
|
-
To read about the problem with the standard analyzer, read the docstring of the function 'create_wildcard'.
|
|
73
|
-
|
|
74
|
-
:param field_name: str, the name of the field to search in.
|
|
75
|
-
:param search_term: str, the search term with the wildcard '*'.
|
|
76
|
-
:return: dict, the wildcard query.
|
|
77
|
-
"""
|
|
78
|
-
|
|
79
|
-
return {
|
|
80
|
-
"query": {
|
|
81
|
-
"wildcard": {
|
|
82
|
-
f"{field_name}.keyword": {
|
|
83
|
-
"value": search_term
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def create_pagination(page: int, size: int) -> dict:
|
|
91
|
-
"""
|
|
92
|
-
Create the pagination query for Elasticsearch.
|
|
93
|
-
|
|
94
|
-
:param page: int, the page number.
|
|
95
|
-
:param size: int, the number of results per page.
|
|
96
|
-
:return: dict, the pagination query.
|
|
97
|
-
"""
|
|
98
|
-
|
|
99
|
-
# Calculate the "from" parameter for Elasticsearch
|
|
100
|
-
start_from = (page - 1) * size
|
|
101
|
-
|
|
102
|
-
# Elasticsearch query
|
|
103
|
-
return {
|
|
104
|
-
"from": start_from,
|
|
105
|
-
"size": size,
|
|
106
|
-
"query": {
|
|
107
|
-
"match_all": {}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def create_pagination_latest_entries(page: int, size: int, sort_by_time_field_name: str = None):
|
|
113
|
-
"""
|
|
114
|
-
Create the pagination query for Elasticsearch.
|
|
115
|
-
This query will sort the results by the 'sort_by_time_field_name' field in descending order.
|
|
116
|
-
This query will return the latest entries.
|
|
117
|
-
|
|
118
|
-
:param page: int, the page number.
|
|
119
|
-
:param size: int, the number of results per page.
|
|
120
|
-
:param sort_by_time_field_name: str, the name of the field to sort by.
|
|
121
|
-
:return: dict, the pagination query.
|
|
122
|
-
"""
|
|
123
|
-
|
|
124
|
-
if sort_by_time_field_name is None:
|
|
125
|
-
sort_by_time_field_name = "timestamp"
|
|
126
|
-
|
|
127
|
-
# Get the pagination query.
|
|
128
|
-
query = create_pagination(page=page, size=size)
|
|
129
|
-
|
|
130
|
-
sorting: dict = {
|
|
131
|
-
"sort": [
|
|
132
|
-
{sort_by_time_field_name: {"order": "desc"}} # Sort by the 'timestamp' field in descending order.
|
|
133
|
-
]
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return query.update(sorting)
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
def add_maximum_size(query: dict):
|
|
140
|
-
"""
|
|
141
|
-
Add the maximum size to the query.
|
|
142
|
-
The maximum size is 10000 for regular queries.
|
|
143
|
-
If you need more than 10000 results, you need to use the 'scroll' API or Search After.
|
|
144
|
-
|
|
145
|
-
:param query: dict, the query to add the maximum size to.
|
|
146
|
-
:return: dict, the query with the maximum size.
|
|
147
|
-
"""
|
|
148
|
-
|
|
149
|
-
query['size'] = 10000
|
|
File without changes
|
|
File without changes
|
|
File without changes
|