weaviate-haystack 1.0.2__tar.gz → 2.0.0__tar.gz

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.
Files changed (23) hide show
  1. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/.gitignore +1 -0
  2. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/PKG-INFO +3 -3
  3. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/docker-compose.yml +2 -2
  4. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/pydoc/config.yml +1 -0
  5. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/pyproject.toml +13 -10
  6. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/src/haystack_integrations/components/retrievers/weaviate/bm25_retriever.py +41 -4
  7. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/src/haystack_integrations/components/retrievers/weaviate/embedding_retriever.py +52 -9
  8. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/src/haystack_integrations/document_stores/weaviate/_filters.py +41 -60
  9. weaviate_haystack-2.0.0/src/haystack_integrations/document_stores/weaviate/document_store.py +497 -0
  10. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/tests/test_bm25_retriever.py +0 -8
  11. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/tests/test_document_store.py +91 -53
  12. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/tests/test_embedding_retriever.py +2 -10
  13. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/tests/test_filters.py +1 -1
  14. weaviate_haystack-1.0.2/src/haystack_integrations/document_stores/weaviate/document_store.py +0 -470
  15. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/LICENSE.txt +0 -0
  16. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/README.md +0 -0
  17. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/src/haystack_integrations/components/retrievers/weaviate/__init__.py +0 -0
  18. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/src/haystack_integrations/document_stores/weaviate/__init__.py +0 -0
  19. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/src/haystack_integrations/document_stores/weaviate/auth.py +0 -0
  20. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/tests/__init__.py +0 -0
  21. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/tests/conftest.py +0 -0
  22. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/tests/test_auth.py +0 -0
  23. {weaviate_haystack-1.0.2 → weaviate_haystack-2.0.0}/tests/test_files/robot1.jpg +0 -0
@@ -134,3 +134,4 @@ dmypy.json
134
134
 
135
135
  # Docs generation artifacts
136
136
  _readme_*.md
137
+ .idea
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: weaviate-haystack
3
- Version: 1.0.2
3
+ Version: 2.0.0
4
4
  Summary: An integration of Weaviate vector database with Haystack
5
5
  Project-URL: Source, https://github.com/deepset-ai/haystack-core-integrations
6
6
  Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/blob/main/integrations/weaviate/README.md
@@ -21,7 +21,7 @@ Requires-Python: >=3.8
21
21
  Requires-Dist: haystack-ai
22
22
  Requires-Dist: haystack-pydoc-tools
23
23
  Requires-Dist: python-dateutil
24
- Requires-Dist: weaviate-client==3.*
24
+ Requires-Dist: weaviate-client
25
25
  Description-Content-Type: text/markdown
26
26
 
27
27
  # weaviate-haystack
@@ -8,7 +8,7 @@ services:
8
8
  - '8080'
9
9
  - --scheme
10
10
  - http
11
- image: semitechnologies/weaviate:1.23.2
11
+ image: semitechnologies/weaviate:1.24.5
12
12
  ports:
13
13
  - 8080:8080
14
14
  - 50051:50051
@@ -19,4 +19,4 @@ services:
19
19
  PERSISTENCE_DATA_PATH: '/var/lib/weaviate'
20
20
  DEFAULT_VECTORIZER_MODULE: 'none'
21
21
  ENABLE_MODULES: ''
22
- CLUSTER_HOSTNAME: 'node1'
22
+ CLUSTER_HOSTNAME: 'node1'
@@ -26,6 +26,7 @@ renderer:
26
26
  order: 250
27
27
  markdown:
28
28
  descriptive_class_title: false
29
+ classdef_code_block: false
29
30
  descriptive_module_title: true
30
31
  add_method_class_prefix: true
31
32
  add_member_class_prefix: false
@@ -24,7 +24,7 @@ classifiers = [
24
24
  ]
25
25
  dependencies = [
26
26
  "haystack-ai",
27
- "weaviate-client==3.*",
27
+ "weaviate-client",
28
28
  "haystack-pydoc-tools",
29
29
  "python-dateutil",
30
30
  ]
@@ -67,12 +67,12 @@ fmt = ["black {args:.}", "ruff --fix {args:.}", "style"]
67
67
  all = ["style", "typing"]
68
68
 
69
69
  [tool.black]
70
- target-version = ["py37"]
70
+ target-version = ["py38"]
71
71
  line-length = 120
72
72
  skip-string-normalization = true
73
73
 
74
74
  [tool.ruff]
75
- target-version = "py37"
75
+ target-version = "py38"
76
76
  line-length = 120
77
77
  select = [
78
78
  "A",
@@ -133,17 +133,20 @@ ban-relative-imports = "parents"
133
133
  "tests/**/*" = ["PLR2004", "S101", "TID252"]
134
134
 
135
135
  [tool.coverage.run]
136
- source_pkgs = ["src", "tests"]
136
+ source = ["haystack_integrations"]
137
137
  branch = true
138
- parallel = true
138
+ parallel = false
139
139
 
140
140
 
141
- [tool.coverage.paths]
142
- weaviate_haystack = ["src/haystack_integrations", "*/weaviate-haystack/src"]
143
- tests = ["tests", "*/weaviate-haystack/tests"]
144
-
145
141
  [tool.coverage.report]
146
- exclude_lines = ["no cov", "if __name__ == .__main__.:", "if TYPE_CHECKING:"]
142
+ omit = ["*/tests/*", "*/__init__.py"]
143
+ show_missing=true
144
+ exclude_lines = [
145
+ "no cov",
146
+ "if __name__ == .__main__.:",
147
+ "if TYPE_CHECKING:",
148
+ ]
149
+
147
150
 
148
151
  [[tool.mypy.overrides]]
149
152
  module = [
@@ -7,7 +7,17 @@ from haystack_integrations.document_stores.weaviate import WeaviateDocumentStore
7
7
  @component
8
8
  class WeaviateBM25Retriever:
9
9
  """
10
- Retriever that uses BM25 to find the most promising documents for a given query.
10
+ A component for retrieving documents from Weaviate using the BM25 algorithm.
11
+
12
+ Example usage:
13
+ ```python
14
+ from haystack_integrations.document_stores.weaviate.document_store import WeaviateDocumentStore
15
+ from haystack_integrations.components.retrievers.weaviate.bm25_retriever import WeaviateBM25Retriever
16
+
17
+ document_store = WeaviateDocumentStore(url="http://localhost:8080")
18
+ retriever = WeaviateBM25Retriever(document_store=document_store)
19
+ retriever.run(query="How to make a pizza", top_k=3)
20
+ ```
11
21
  """
12
22
 
13
23
  def __init__(
@@ -20,15 +30,24 @@ class WeaviateBM25Retriever:
20
30
  """
21
31
  Create a new instance of WeaviateBM25Retriever.
22
32
 
23
- :param document_store: Instance of WeaviateDocumentStore that will be associated with this retriever.
24
- :param filters: Custom filters applied when running the retriever, defaults to None
25
- :param top_k: Maximum number of documents to return, defaults to 10
33
+ :param document_store:
34
+ Instance of WeaviateDocumentStore that will be used from this retriever.
35
+ :param filters:
36
+ Custom filters applied when running the retriever
37
+ :param top_k:
38
+ Maximum number of documents to return
26
39
  """
27
40
  self._document_store = document_store
28
41
  self._filters = filters or {}
29
42
  self._top_k = top_k
30
43
 
31
44
  def to_dict(self) -> Dict[str, Any]:
45
+ """
46
+ Serializes the component to a dictionary.
47
+
48
+ :returns:
49
+ Dictionary with serialized data.
50
+ """
32
51
  return default_to_dict(
33
52
  self,
34
53
  filters=self._filters,
@@ -38,6 +57,14 @@ class WeaviateBM25Retriever:
38
57
 
39
58
  @classmethod
40
59
  def from_dict(cls, data: Dict[str, Any]) -> "WeaviateBM25Retriever":
60
+ """
61
+ Deserializes the component from a dictionary.
62
+
63
+ :param data:
64
+ Dictionary to deserialize from.
65
+ :returns:
66
+ Deserialized component.
67
+ """
41
68
  data["init_parameters"]["document_store"] = WeaviateDocumentStore.from_dict(
42
69
  data["init_parameters"]["document_store"]
43
70
  )
@@ -45,6 +72,16 @@ class WeaviateBM25Retriever:
45
72
 
46
73
  @component.output_types(documents=List[Document])
47
74
  def run(self, query: str, filters: Optional[Dict[str, Any]] = None, top_k: Optional[int] = None):
75
+ """
76
+ Retrieves documents from Weaviate using the BM25 algorithm.
77
+
78
+ :param query:
79
+ The query text.
80
+ :param filters:
81
+ Filters to use when running the retriever.
82
+ :param top_k:
83
+ The maximum number of documents to return.
84
+ """
48
85
  filters = filters or self._filters
49
86
  top_k = top_k or self._top_k
50
87
  documents = self._document_store._bm25_retrieval(query=query, filters=filters, top_k=top_k)
@@ -20,16 +20,22 @@ class WeaviateEmbeddingRetriever:
20
20
  certainty: Optional[float] = None,
21
21
  ):
22
22
  """
23
- Create a new instance of WeaviateEmbeddingRetriever.
24
- Raises ValueError if both `distance` and `certainty` are provided.
25
- See the official Weaviate documentation to learn more about the `distance` and `certainty` parameters:
26
- https://weaviate.io/developers/weaviate/api/graphql/search-operators#variables
23
+ Creates a new instance of WeaviateEmbeddingRetriever.
27
24
 
28
- :param document_store: Instance of WeaviateDocumentStore that will be associated with this retriever.
29
- :param filters: Custom filters applied when running the retriever, defaults to None
30
- :param top_k: Maximum number of documents to return, defaults to 10
31
- :param distance: The maximum allowed distance between Documents' embeddings, defaults to None
32
- :param certainty: Normalized distance between the result item and the search vector, defaults to None
25
+ :param document_store:
26
+ Instance of WeaviateDocumentStore that will be used from this retriever.
27
+ :param filters:
28
+ Custom filters applied when running the retriever.
29
+ :param top_k:
30
+ Maximum number of documents to return.
31
+ :param distance:
32
+ The maximum allowed distance between Documents' embeddings.
33
+ :param certainty:
34
+ Normalized distance between the result item and the search vector.
35
+ :raises ValueError:
36
+ If both `distance` and `certainty` are provided.
37
+ See https://weaviate.io/developers/weaviate/api/graphql/search-operators#variables to learn more about
38
+ `distance` and `certainty` parameters.
33
39
  """
34
40
  if distance is not None and certainty is not None:
35
41
  msg = "Can't use 'distance' and 'certainty' parameters together"
@@ -42,6 +48,12 @@ class WeaviateEmbeddingRetriever:
42
48
  self._certainty = certainty
43
49
 
44
50
  def to_dict(self) -> Dict[str, Any]:
51
+ """
52
+ Serializes the component to a dictionary.
53
+
54
+ :returns:
55
+ Dictionary with serialized data.
56
+ """
45
57
  return default_to_dict(
46
58
  self,
47
59
  filters=self._filters,
@@ -53,6 +65,14 @@ class WeaviateEmbeddingRetriever:
53
65
 
54
66
  @classmethod
55
67
  def from_dict(cls, data: Dict[str, Any]) -> "WeaviateEmbeddingRetriever":
68
+ """
69
+ Deserializes the component from a dictionary.
70
+
71
+ :param data:
72
+ Dictionary to deserialize from.
73
+ :returns:
74
+ Deserialized component.
75
+ """
56
76
  data["init_parameters"]["document_store"] = WeaviateDocumentStore.from_dict(
57
77
  data["init_parameters"]["document_store"]
58
78
  )
@@ -67,10 +87,33 @@ class WeaviateEmbeddingRetriever:
67
87
  distance: Optional[float] = None,
68
88
  certainty: Optional[float] = None,
69
89
  ):
90
+ """
91
+ Retrieves documents from Weaviate using the vector search.
92
+
93
+ :param query_embedding:
94
+ Embedding of the query.
95
+ :param filters:
96
+ Filters to use when running the retriever.
97
+ :param top_k:
98
+ The maximum number of documents to return.
99
+ :param distance:
100
+ The maximum allowed distance between Documents' embeddings.
101
+ :param certainty:
102
+ Normalized distance between the result item and the search vector.
103
+ :raises ValueError:
104
+ If both `distance` and `certainty` are provided.
105
+ See https://weaviate.io/developers/weaviate/api/graphql/search-operators#variables to learn more about
106
+ `distance` and `certainty` parameters.
107
+ """
70
108
  filters = filters or self._filters
71
109
  top_k = top_k or self._top_k
110
+
72
111
  distance = distance or self._distance
73
112
  certainty = certainty or self._certainty
113
+ if distance is not None and certainty is not None:
114
+ msg = "Can't use 'distance' and 'certainty' parameters together"
115
+ raise ValueError(msg)
116
+
74
117
  documents = self._document_store._embedding_retrieval(
75
118
  query_embedding=query_embedding,
76
119
  filters=filters,
@@ -4,8 +4,11 @@ from dateutil import parser
4
4
  from haystack.errors import FilterError
5
5
  from pandas import DataFrame
6
6
 
7
+ import weaviate
8
+ from weaviate.collections.classes.filters import Filter, FilterReturn
7
9
 
8
- def convert_filters(filters: Dict[str, Any]) -> Dict[str, Any]:
10
+
11
+ def convert_filters(filters: Dict[str, Any]) -> FilterReturn:
9
12
  """
10
13
  Convert filters from Haystack format to Weaviate format.
11
14
  """
@@ -14,7 +17,7 @@ def convert_filters(filters: Dict[str, Any]) -> Dict[str, Any]:
14
17
  raise FilterError(msg)
15
18
 
16
19
  if "field" in filters:
17
- return {"operator": "And", "operands": [_parse_comparison_condition(filters)]}
20
+ return Filter.all_of([_parse_comparison_condition(filters)])
18
21
  return _parse_logical_condition(filters)
19
22
 
20
23
 
@@ -29,7 +32,7 @@ OPERATOR_INVERSE = {
29
32
  "not in": "in",
30
33
  "AND": "OR",
31
34
  "OR": "AND",
32
- "NOT": "AND",
35
+ "NOT": "OR",
33
36
  }
34
37
 
35
38
 
@@ -51,7 +54,13 @@ def _invert_condition(filters: Dict[str, Any]) -> Dict[str, Any]:
51
54
  return inverted_condition
52
55
 
53
56
 
54
- def _parse_logical_condition(condition: Dict[str, Any]) -> Dict[str, Any]:
57
+ LOGICAL_OPERATORS = {
58
+ "AND": Filter.all_of,
59
+ "OR": Filter.any_of,
60
+ }
61
+
62
+
63
+ def _parse_logical_condition(condition: Dict[str, Any]) -> FilterReturn:
55
64
  if "operator" not in condition:
56
65
  msg = f"'operator' key missing in {condition}"
57
66
  raise FilterError(msg)
@@ -67,7 +76,7 @@ def _parse_logical_condition(condition: Dict[str, Any]) -> Dict[str, Any]:
67
76
  operands.append(_parse_logical_condition(c))
68
77
  else:
69
78
  operands.append(_parse_comparison_condition(c))
70
- return {"operator": operator.lower().capitalize(), "operands": operands}
79
+ return LOGICAL_OPERATORS[operator](operands)
71
80
  elif operator == "NOT":
72
81
  inverted_conditions = _invert_condition(condition)
73
82
  return _parse_logical_condition(inverted_conditions)
@@ -76,28 +85,6 @@ def _parse_logical_condition(condition: Dict[str, Any]) -> Dict[str, Any]:
76
85
  raise FilterError(msg)
77
86
 
78
87
 
79
- def _infer_value_type(value: Any) -> str:
80
- if value is None:
81
- return "valueNull"
82
-
83
- if isinstance(value, bool):
84
- return "valueBoolean"
85
- if isinstance(value, int):
86
- return "valueInt"
87
- if isinstance(value, float):
88
- return "valueNumber"
89
-
90
- if isinstance(value, str):
91
- try:
92
- parser.isoparse(value)
93
- return "valueDate"
94
- except ValueError:
95
- return "valueText"
96
-
97
- msg = f"Unknown value type {type(value)}"
98
- raise FilterError(msg)
99
-
100
-
101
88
  def _handle_date(value: Any) -> str:
102
89
  if isinstance(value, str):
103
90
  try:
@@ -107,25 +94,22 @@ def _handle_date(value: Any) -> str:
107
94
  return value
108
95
 
109
96
 
110
- def _equal(field: str, value: Any) -> Dict[str, Any]:
97
+ def _equal(field: str, value: Any) -> FilterReturn:
111
98
  if value is None:
112
- return {"path": field, "operator": "IsNull", "valueBoolean": True}
113
- return {"path": field, "operator": "Equal", _infer_value_type(value): _handle_date(value)}
99
+ return weaviate.classes.query.Filter.by_property(field).is_none(True)
100
+ return weaviate.classes.query.Filter.by_property(field).equal(_handle_date(value))
114
101
 
115
102
 
116
- def _not_equal(field: str, value: Any) -> Dict[str, Any]:
103
+ def _not_equal(field: str, value: Any) -> FilterReturn:
117
104
  if value is None:
118
- return {"path": field, "operator": "IsNull", "valueBoolean": False}
119
- return {
120
- "operator": "Or",
121
- "operands": [
122
- {"path": field, "operator": "NotEqual", _infer_value_type(value): _handle_date(value)},
123
- {"path": field, "operator": "IsNull", "valueBoolean": True},
124
- ],
125
- }
105
+ return weaviate.classes.query.Filter.by_property(field).is_none(False)
126
106
 
107
+ return weaviate.classes.query.Filter.by_property(field).not_equal(
108
+ _handle_date(value)
109
+ ) | weaviate.classes.query.Filter.by_property(field).is_none(True)
127
110
 
128
- def _greater_than(field: str, value: Any) -> Dict[str, Any]:
111
+
112
+ def _greater_than(field: str, value: Any) -> FilterReturn:
129
113
  if value is None:
130
114
  # When the value is None and '>' is used we create a filter that would return a Document
131
115
  # if it has a field set and not set at the same time.
@@ -144,10 +128,10 @@ def _greater_than(field: str, value: Any) -> Dict[str, Any]:
144
128
  if type(value) in [list, DataFrame]:
145
129
  msg = f"Filter value can't be of type {type(value)} using operators '>', '>=', '<', '<='"
146
130
  raise FilterError(msg)
147
- return {"path": field, "operator": "GreaterThan", _infer_value_type(value): _handle_date(value)}
131
+ return weaviate.classes.query.Filter.by_property(field).greater_than(_handle_date(value))
148
132
 
149
133
 
150
- def _greater_than_equal(field: str, value: Any) -> Dict[str, Any]:
134
+ def _greater_than_equal(field: str, value: Any) -> FilterReturn:
151
135
  if value is None:
152
136
  # When the value is None and '>=' is used we create a filter that would return a Document
153
137
  # if it has a field set and not set at the same time.
@@ -166,10 +150,10 @@ def _greater_than_equal(field: str, value: Any) -> Dict[str, Any]:
166
150
  if type(value) in [list, DataFrame]:
167
151
  msg = f"Filter value can't be of type {type(value)} using operators '>', '>=', '<', '<='"
168
152
  raise FilterError(msg)
169
- return {"path": field, "operator": "GreaterThanEqual", _infer_value_type(value): _handle_date(value)}
153
+ return weaviate.classes.query.Filter.by_property(field).greater_or_equal(_handle_date(value))
170
154
 
171
155
 
172
- def _less_than(field: str, value: Any) -> Dict[str, Any]:
156
+ def _less_than(field: str, value: Any) -> FilterReturn:
173
157
  if value is None:
174
158
  # When the value is None and '<' is used we create a filter that would return a Document
175
159
  # if it has a field set and not set at the same time.
@@ -188,10 +172,10 @@ def _less_than(field: str, value: Any) -> Dict[str, Any]:
188
172
  if type(value) in [list, DataFrame]:
189
173
  msg = f"Filter value can't be of type {type(value)} using operators '>', '>=', '<', '<='"
190
174
  raise FilterError(msg)
191
- return {"path": field, "operator": "LessThan", _infer_value_type(value): _handle_date(value)}
175
+ return weaviate.classes.query.Filter.by_property(field).less_than(_handle_date(value))
192
176
 
193
177
 
194
- def _less_than_equal(field: str, value: Any) -> Dict[str, Any]:
178
+ def _less_than_equal(field: str, value: Any) -> FilterReturn:
195
179
  if value is None:
196
180
  # When the value is None and '<=' is used we create a filter that would return a Document
197
181
  # if it has a field set and not set at the same time.
@@ -210,22 +194,23 @@ def _less_than_equal(field: str, value: Any) -> Dict[str, Any]:
210
194
  if type(value) in [list, DataFrame]:
211
195
  msg = f"Filter value can't be of type {type(value)} using operators '>', '>=', '<', '<='"
212
196
  raise FilterError(msg)
213
- return {"path": field, "operator": "LessThanEqual", _infer_value_type(value): _handle_date(value)}
197
+ return weaviate.classes.query.Filter.by_property(field).less_or_equal(_handle_date(value))
214
198
 
215
199
 
216
- def _in(field: str, value: Any) -> Dict[str, Any]:
200
+ def _in(field: str, value: Any) -> FilterReturn:
217
201
  if not isinstance(value, list):
218
202
  msg = f"{field}'s value must be a list when using 'in' or 'not in' comparators"
219
203
  raise FilterError(msg)
220
204
 
221
- return {"operator": "And", "operands": [_equal(field, v) for v in value]}
205
+ return weaviate.classes.query.Filter.by_property(field).contains_any(value)
222
206
 
223
207
 
224
- def _not_in(field: str, value: Any) -> Dict[str, Any]:
208
+ def _not_in(field: str, value: Any) -> FilterReturn:
225
209
  if not isinstance(value, list):
226
210
  msg = f"{field}'s value must be a list when using 'in' or 'not in' comparators"
227
211
  raise FilterError(msg)
228
- return {"operator": "And", "operands": [_not_equal(field, v) for v in value]}
212
+ operands = [weaviate.classes.query.Filter.by_property(field).not_equal(v) for v in value]
213
+ return Filter.all_of(operands)
229
214
 
230
215
 
231
216
  COMPARISON_OPERATORS = {
@@ -240,7 +225,7 @@ COMPARISON_OPERATORS = {
240
225
  }
241
226
 
242
227
 
243
- def _parse_comparison_condition(condition: Dict[str, Any]) -> Dict[str, Any]:
228
+ def _parse_comparison_condition(condition: Dict[str, Any]) -> FilterReturn:
244
229
  field: str = condition["field"]
245
230
 
246
231
  if field.startswith("meta."):
@@ -265,15 +250,11 @@ def _parse_comparison_condition(condition: Dict[str, Any]) -> Dict[str, Any]:
265
250
  return COMPARISON_OPERATORS[operator](field, value)
266
251
 
267
252
 
268
- def _match_no_document(field: str) -> Dict[str, Any]:
253
+ def _match_no_document(field: str) -> FilterReturn:
269
254
  """
270
255
  Returns a filters that will match no Document, this is used to keep the behavior consistent
271
256
  between different Document Stores.
272
257
  """
273
- return {
274
- "operator": "And",
275
- "operands": [
276
- {"path": field, "operator": "IsNull", "valueBoolean": False},
277
- {"path": field, "operator": "IsNull", "valueBoolean": True},
278
- ],
279
- }
258
+
259
+ operands = [weaviate.classes.query.Filter.by_property(field).is_none(val) for val in [False, True]]
260
+ return Filter.all_of(operands)