使用合并与一个单一的创建调用在FaunaDB创建两个文档?



使用FaunaDB与Node.js在Netlify Function上运行时出现了一个奇怪的错误。

我正在构建一个快速的概念验证,最初一切都很好。我有一个创建查询,看起来像这样:

const faunadb = require('faunadb');
const q = faunadb.query;
const CreateFarm = (data) => (
q.Create(
q.Collection('farms'),
{ data },
)
);

正如我所说的,这里的一切都如预期的那样工作。当我试图开始规范化FaunaDB发回的数据时,问题就开始了。具体来说,我想将fauna生成的ID合并到data对象中,并将其发送回来,而不包含任何其他元数据。

我已经在用其他资源做了,所以我写了一个助手查询并合并了它:

const faunadb = require('faunadb');
const q = faunadb.query;
const Normalize = (resource) => (
q.Merge(
q.Select(['data'], resource),
{ id: q.Select(['ref', 'id'], resource) },
)
);
const CreateFarm = (data) => (
Normalize(
q.Create(
q.Collection('farms'),
{ data },
),
)
);

这个Normalize函数在其他地方都像预期的那样工作。它用一个没有奇怪副作用的ID构建正确的合并对象。然而,当与CreateFarm一起使用时,我最终在DB中使用两个相同的农场!!

我花了很长时间看应用程序的其余部分。肯定只有一个POST请求进来,CreateFarm肯定只被调用一次。我最好的理论是,由于Merge复制传递给它的第一个资源,Create不知怎么地在DB上被调用了两次。但是重新排序Merge调用不会改变任何东西。我甚至尝试先传入一个空对象,但最后总是创建两个相同的对象。

您的助手使用两个单独的Create表达式创建一个FQL查询。每个都被计算并创建一个新的Document。这与Merge函数无关。

Merge(
Select(['data'], Create(
Collection('farms'),
{ data },
)),
{ id: Select(['ref', 'id'], Create(
Collection('farms'),
{ data },
)) },
)

使用Let创建文档,然后使用Update创建带有id的文档。注意,这会增加应用程序所需的写操作的数量。这将使创建文档的成本增加一倍。但是对于你想要做的事情,这是应该做的。

Let(
{
newDoc: Create(q.Collection("farms"), { data }),
id: Select(["ref", "id"], Var("newDoc")),
data: Select(["data"], Var("newDoc"))
},
Update(
Select(["ref"], Var("newDoc")), 
{
data: Merge(
Var("data"), 
{ id: Var("id") }
)
}
)
)

旁白:为什么在文档数据中存储id ?不清楚为什么你可能需要这样做。索引可以在ref值本身上创建。如果你的客户端接收到一个Ref,那么它可以直接传递到后续的查询中。根据我的经验,如果你需要在应用程序中直接使用普通的id值,那么在应用程序中尽可能地转换Document(比如使用id作为web组件数组的键)。

使用Ref比从集合名称和ID重新构建Ref表达式在计算上甚至有一点优势。表达式Ref(Collection("farms"), "1234")在计算成本上算作2个FQL函数,但是重用查询返回的Ref是免费的。

使用GraphQL时,_id字段被抽象出来,因为在GraphQL中处理文档类型会非常糟糕。然而,FQL查询的最佳实践是尽可能直接使用Ref。

不过,别让我用绝对的术语来说话!一般来说,我相信任何事情都是有原因的。如果您认为确实需要复制Documents数据中的ID,那么我很想知道为什么。

相关内容

  • 没有找到相关文章

最新更新