beanie/bunnet Delete all references of a document in another collection

68 Views Asked by At

I am using Bunnet (a synchronous fork of Beanie) and I want to be able to delete a document and all its references to it.

For instance, let's take a dummy example. Let's say that I have an Author collection and a Book collection. A Book can be written by several authors. I want that if I delete an author, all the references to that author are also deleted from the database. Though, I don't want to delete the book reference unless the book is no longer attached to any author. How can I do that cleanly ? I also rather not have a "fetch_link=True" because the database is in such a way that the link connections will basically pull the whole database each time.

from typing import List
from bunnet import Document, Link, init_bunnet, before_event, Delete, BackLink, DeleteRules
from pydantic import Field
import pymongo

class Author(Document):
    name: str
    books: List[BackLink["Book"]] = Field(original_field="authors")

    @before_event(Delete)
    def hello(self):
        print(f"DELETING Author {self.name}")

class Book(Document):
    title: str
    authors: List[Link[Author]]

    @before_event(Delete)
    def hello(self):
        print(f"DELETING book {self.title}")

def setup():
    # Connect to MongoDB
    client = pymongo.MongoClient("mongodb://localhost:27017")
    db = client["bunnettest"]
    # Initialize Beanie with document models
    init_bunnet(database=db, document_models=[Book, Author])

def create_initial_data():
    # Initialize the database and documents
    setup()
    Author.delete_all()
    Book.delete_all()
    # Create Authors
    author1 = Author(name="Author One").create()
    author2 = Author(name="Author Two").create()
    author3 = Author(name="Author Three").create()

    # Create Books with Authors
    Book(title="Book One", authors=[author1, author2]).create()
    Book(title="Book Two", authors=[author2]).create()
    Book(title="Book Three", authors=[author1, author2, author3]).create()

    print("Data Initialized.")

create_initial_data()


author = Author.find_one(Author.name == "Author Two").run()
if author:
    ...
    # Here I want to delete all the reference of this author in the books
    # and also do
    # author.delete()
else:
    print("already deleted")

What is the nicest way to do what I want?

I tried to fiddle a bit with Pull, PullAll, but I have not manage to get it working. Using DeleteRules.DELETE_LINKS basically delete all the database because it deletes the linked document and not the references inside these document. I even tried loading all the books that have the Author I want to delete so that I can delete the reference by rewritting the authors list but I find it quite quirky.

Thank you for your help

0

There are 0 best solutions below