Skip to content

Commit 9eeb3ec

Browse files
authored
DE-743 | MDI/ZKD Indexes (#316)
* DE-743 | initial commit * fix: `format_index` * remove `sparse` assertion (zkd & mdi indexes don't support the `sparse` property` * cleanup * use `split` on `db_version` allows us to test with a nightly build, e.g `3.12.0-NIGHTLY.20240116`
1 parent 474359e commit 9eeb3ec

File tree

4 files changed

+147
-1
lines changed

4 files changed

+147
-1
lines changed

arango/collection.py

+83
Original file line numberDiff line numberDiff line change
@@ -1617,6 +1617,89 @@ def add_inverted_index(
16171617

16181618
return self._add_index(data)
16191619

1620+
def add_zkd_index(
1621+
self,
1622+
fields: Sequence[str],
1623+
field_value_types: str = "double",
1624+
name: Optional[str] = None,
1625+
unique: Optional[bool] = None,
1626+
in_background: Optional[bool] = None,
1627+
) -> Result[Json]:
1628+
"""Create a new ZKD Index.
1629+
1630+
:param fields: Document fields to index. Unlike for other indexes the
1631+
order of the fields does not matter.
1632+
:type fields: Sequence[str]
1633+
:param field_value_types: The type of the field values. The only allowed
1634+
value is "double" at the moment. Defaults to "double".
1635+
:type field_value_types: str
1636+
:param name: Optional name for the index.
1637+
:type name: str | None
1638+
:param unique: Whether the index is unique.
1639+
:type unique: bool | None
1640+
:param in_background: Do not hold the collection lock.
1641+
:type in_background: bool | None
1642+
:return: New index details.
1643+
:rtype: dict
1644+
:raise arango.exceptions.IndexCreateError: If create fails.
1645+
"""
1646+
data: Json = {
1647+
"type": "zkd",
1648+
"fields": fields,
1649+
"fieldValueTypes": field_value_types,
1650+
}
1651+
1652+
if unique is not None:
1653+
data["unique"] = unique
1654+
if name is not None:
1655+
data["name"] = name
1656+
if in_background is not None:
1657+
data["inBackground"] = in_background
1658+
1659+
return self._add_index(data)
1660+
1661+
def add_mdi_index(
1662+
self,
1663+
fields: Sequence[str],
1664+
field_value_types: str = "double",
1665+
name: Optional[str] = None,
1666+
unique: Optional[bool] = None,
1667+
in_background: Optional[bool] = None,
1668+
) -> Result[Json]:
1669+
"""Create a new MDI index, previously known as ZKD index. This method
1670+
is only usable with ArangoDB 3.12 and later.
1671+
1672+
:param fields: Document fields to index. Unlike for other indexes the
1673+
order of the fields does not matter.
1674+
:type fields: Sequence[str]
1675+
:param field_value_types: The type of the field values. The only allowed
1676+
value is "double" at the moment. Defaults to "double".
1677+
:type field_value_types: str
1678+
:param name: Optional name for the index.
1679+
:type name: str | None
1680+
:param unique: Whether the index is unique.
1681+
:type unique: bool | None
1682+
:param in_background: Do not hold the collection lock.
1683+
:type in_background: bool | None
1684+
:return: New index details.
1685+
:rtype: dict
1686+
:raise arango.exceptions.IndexCreateError: If create fails.
1687+
"""
1688+
data: Json = {
1689+
"type": "mdi",
1690+
"fields": fields,
1691+
"fieldValueTypes": field_value_types,
1692+
}
1693+
1694+
if unique is not None:
1695+
data["unique"] = unique
1696+
if name is not None:
1697+
data["name"] = name
1698+
if in_background is not None:
1699+
data["inBackground"] = in_background
1700+
1701+
return self._add_index(data)
1702+
16201703
def delete_index(self, index_id: str, ignore_missing: bool = False) -> Result[bool]:
16211704
"""Delete an index.
16221705

arango/formatter.py

+2
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ def format_index(body: Json) -> Json:
101101
result["writebuffer_active"] = body["writebufferActive"]
102102
if "writebufferSizeMax" in body:
103103
result["writebuffer_max_size"] = body["writebufferSizeMax"]
104+
if "fieldValueTypes" in body:
105+
result["field_value_types"] = body["fieldValueTypes"]
104106

105107
return verify_format(body, result)
106108

tests/conftest.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def pytest_configure(config):
134134
global_data.username = username
135135
global_data.password = password
136136
global_data.db_name = tst_db_name
137-
global_data.db_version = version.parse(db_version)
137+
global_data.db_version = version.parse(db_version.split("-")[0])
138138
global_data.sys_db = sys_db
139139
global_data.tst_db = tst_db
140140
global_data.bad_db = bad_db

tests/test_index.py

+61
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,67 @@ def test_add_inverted_index(icol, enterprise, db_version):
248248
icol.delete_index(result["id"])
249249

250250

251+
def test_add_zkd_index(icol, db_version):
252+
result = icol.add_zkd_index(
253+
name="zkd_index",
254+
fields=["x", "y", "z"],
255+
field_value_types="double",
256+
in_background=False,
257+
unique=False,
258+
)
259+
260+
expected_index = {
261+
"name": "zkd_index",
262+
"type": "zkd",
263+
"fields": ["x", "y", "z"],
264+
"new": True,
265+
"unique": False,
266+
}
267+
268+
for key, value in expected_index.items():
269+
assert result[key] == value
270+
271+
assert result["id"] in extract("id", icol.indexes())
272+
273+
with assert_raises(IndexCreateError) as err:
274+
icol.add_zkd_index(field_value_types="integer", fields=["x", "y", "z"])
275+
assert err.value.error_code == 10
276+
277+
icol.delete_index(result["id"])
278+
279+
280+
def test_add_mdi_index(icol, db_version):
281+
if db_version < version.parse("3.12.0"):
282+
pytest.skip("MDI indexes are usable with 3.12+ only")
283+
284+
result = icol.add_mdi_index(
285+
name="mdi_index",
286+
fields=["x", "y", "z"],
287+
field_value_types="double",
288+
in_background=False,
289+
unique=True,
290+
)
291+
292+
expected_index = {
293+
"name": "mdi_index",
294+
"type": "mdi",
295+
"fields": ["x", "y", "z"],
296+
"new": True,
297+
"unique": True,
298+
}
299+
300+
for key, value in expected_index.items():
301+
assert result[key] == value
302+
303+
assert result["id"] in extract("id", icol.indexes())
304+
305+
with assert_raises(IndexCreateError) as err:
306+
icol.add_mdi_index(field_value_types="integer", fields=["x", "y", "z"])
307+
assert err.value.error_code == 10
308+
309+
icol.delete_index(result["id"])
310+
311+
251312
def test_delete_index(icol, bad_col):
252313
old_indexes = set(extract("id", icol.indexes()))
253314
icol.add_hash_index(["attr3", "attr4"], unique=True)

0 commit comments

Comments
 (0)