如何在Python中为Fauna DB创建含其他集合文档引用的文档?
在Python中规范创建Fauna DB带文档引用的集合文档
问题背景
我在Fauna DB中有一个yalofiles集合,Schema定义如下:
collection yalofiles { yaloid: Ref<yalos> yaloContentId: String name: String *: Any }
其中yaloid字段需要引用yalos集合中的文档。当前环境配置:
- Python版本:3.12.5
- PyPi的fauna 2.3.0(Fauna v10官方Python驱动)
我尝试编写代码创建yalofile文档,但遇到了错误。初始代码如下(已移除try/except块):
def insertYalofile(self, yalofile, yaloId): qyalo = fql(f'{YALOS_COLLECTION}.byId({yaloId})') ryalo: QuerySuccess = self._client.query(qyalo) yalofile["yaloid"] = ryalo.data # 这里传入了完整的Document对象 query = fql(f'{YALOFILES_COLLECTION}.create({yalofile})') res: QuerySuccess = self._client.query(query) # 此查询失败 return res.data
执行后抛出错误:
400: invalid_query The query failed 1 validation check --- error: Expected `)` or `,` at *query*:1:40 | 1 | yalofiles.create({'yaloid': Document(id='412701900943655120',coll=Module(name='yalos'),ts=datetime.datetime(2024, 10, 25, 7, 40, 53, 280000, tzinfo=datetime.timezone.utc),data={'name':'alfred stevens','yalotype':'artist','displayname':'Alfred Stevens','owner':'yaluba','artist':'412652432707813579','tags':['412472715978473675']}), 'yaloContentId': '66f5bbd2bff7b6328f8fb52a', 'name': 'alfred stevens', 'isMain': True, 'mime': 'image/jpeg', 'provider': 'cloudflare', 'stosol': 'r2'}) | ^ |
显然直接传入完整Document对象不行。我尝试过使用models.DocumentReference(YALOS_COLLECTION, yaloId),但依然报错。目前只能通过手动拼接FQL字符串实现,但这种方式需要手动处理格式,非常不规范:
yalofilestr = '{ \'yaloid\': yalos(' + yaloId + '), ' + repr(yalofile)[1:] yalofilestr = yalofilestr.replace("True", "true") ; yalofilestr = yalofilestr.replace("False", "false") query = fql(f'{YALOFILES_COLLECTION}.create({yalofilestr})')
请问在Python中,如何规范创建包含其他集合文档引用的Fauna DB集合文档?
规范解决方案
方案1:使用Document对象的ref属性
当你通过byId查询获取到完整Document对象时,直接取它的ref属性即可,这个属性就是符合要求的引用类型:
def insertYalofile(self, yalofile, yaloId): qyalo = fql(f'{YALOS_COLLECTION}.byId({yaloId})') ryalo: QuerySuccess = self._client.query(qyalo) yalofile["yaloid"] = ryalo.data.ref # 使用Document的ref属性 query = fql(f'{YALOFILES_COLLECTION}.create({yalofile})') res: QuerySuccess = self._client.query(query) return res.data
方案2:直接构造引用(无需先查询目标文档)
如果已经知道目标文档的ID,可以直接在FQL中构造引用,不需要提前查询文档,推荐用参数化查询避免字符串拼接风险:
def insertYalofile(self, yalofile, yaloId): # 合并数据并使用参数化查询 create_data = {**yalofile, "yaloid": fql(f"{YALOS_COLLECTION}.byId({yaloId})")} query = fql('${coll}.create(${data})', coll=YALOFILES_COLLECTION, data=create_data) res: QuerySuccess = self._client.query(query) return res.data
方案3:正确使用DocumentReference类
使用DocumentReference时,需要将其作为参数传入FQL查询,而不是直接拼接到字符串中:
from fauna.models import DocumentReference def insertYalofile(self, yalofile, yaloId): yalo_ref = DocumentReference(collection_name=YALOS_COLLECTION, document_id=yaloId) # 合并数据字典与引用 create_data = {**yalofile, "yaloid": yalo_ref} query = fql('${coll}.create(${data})', coll=YALOFILES_COLLECTION, data=create_data) res: QuerySuccess = self._client.query(query) return res.data
内容的提问来源于stack exchange,提问作者juan noguera
相关产品推荐
相关产品推荐

