Skip to content

Add delete_many to support for bulk deletes #305

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Aug 10, 2022
31 changes: 29 additions & 2 deletions aredis_om/model/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -1115,9 +1115,13 @@ def key(self):
return self.make_primary_key(pk)

@classmethod
async def delete(cls, pk: Any) -> int:
async def delete(cls, pk: Any, pipeline: Optional[Pipeline] = None) -> int:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think delete_all and delete should call a new function named _delete underneath, that accepts a kwargs (at least). This would be a bit cleaner.

"""Delete data at this key."""
return await cls.db().delete(cls.make_primary_key(pk))
if pipeline is None:
db = cls.db()
else:
db = pipeline
return await db.delete(cls.make_primary_key(pk))

@classmethod
async def get(cls, pk: Any) -> "RedisModel":
Expand Down Expand Up @@ -1267,6 +1271,29 @@ async def add(

return models

@classmethod
async def delete_all(
cls,
models: Sequence["RedisModel"],
pipeline: Optional[Pipeline] = None,
pipeline_verifier: Callable[..., Any] = verify_pipeline_response,
) -> int:
if pipeline is None:
db = cls.db().pipeline(transaction=False)
else:
db = pipeline

for model in models:
await model.delete(model.pk, pipeline=db)

# If the user didn't give us a pipeline, then we need to execute
# the one we just created.
if pipeline is None:
result = await db.execute()
pipeline_verifier(result, expected_responses=len(models))

return len(models)

@classmethod
def redisearch_schema(cls):
raise NotImplementedError
Expand Down
28 changes: 28 additions & 0 deletions tests/test_hash_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
Migrator,
QueryNotSupportedError,
RedisModelError,
NotFoundError
)

# We need to run this check as sync code (during tests) even in async mode
Expand Down Expand Up @@ -552,6 +553,33 @@ async def test_saves_many(m):
assert await m.Member.get(pk=member2.pk) == member2


@py_test_mark_asyncio
async def test_delete_many(m):
member1 = m.Member(
first_name="Andrew",
last_name="Brookins",
email="[email protected]",
join_date=today,
age=38,
bio="This is the user bio.",
)
member2 = m.Member(
first_name="Kim",
last_name="Brookins",
email="[email protected]",
join_date=today,
age=34,
bio="This is the bio for Kim.",
)
members = [member1, member2]
result = await m.Member.add(members)
assert result == [member1, member2]
result = await m.Member.delete_all(members)
assert result == 2
with pytest.raises(NotFoundError):
await m.Member.get(pk=member1.pk)


@py_test_mark_asyncio
async def test_updates_a_model(members, m):
member1, member2, member3 = members
Expand Down
53 changes: 53 additions & 0 deletions tests/test_json_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,59 @@ async def test_saves_many_explicit_transaction(address, m):
assert await m.Member.get(pk=member2.pk) == member2


@py_test_mark_asyncio
async def test_delete_many_implicit_pipeline(address, m):
member1 = m.Member(
first_name="Andrew",
last_name="Brookins",
email="[email protected]",
join_date=today,
address=address,
age=38,
)
member2 = m.Member(
first_name="Kim",
last_name="Brookins",
email="[email protected]",
join_date=today,
address=address,
age=34,
)
members = [member1, member2]
result = await m.Member.add(members)
assert result == [member1, member2]
result = await m.Member.delete_all(members)
assert result == 2
with pytest.raises(NotFoundError):
await m.Member.get(pk=member2.pk)


@py_test_mark_asyncio
async def test_delete_many_explicit_transaction(address, m):
member1 = m.Member(
first_name="Andrew",
last_name="Brookins",
email="[email protected]",
join_date=today,
address=address,
age=38,
)
member2 = m.Member(
first_name="Kim",
last_name="Brookins",
email="[email protected]",
join_date=today,
address=address,
age=34,
)
members = [member1, member2]
result = await m.Member.add(members)
assert result == [member1, member2]
async with m.Member.db().pipeline(transaction=True) as pipeline:
await m.Member.delete_all(members, pipeline=pipeline)
assert await pipeline.execute() == [1, 1]


async def save(members):
for m in members:
await m.save()
Expand Down