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