在 FaunaDB 中将 Merge 与单个 Create 调用结合使用会创建两个文档吗?
Using Merge with a single Create call in FaunaDB is creating two documents?
在 Netlify 函数上使用带有 Node.js 运行 的 FaunaDB 时遇到一个奇怪的错误。
我正在建立一个快速的概念验证,最初一切正常。我有一个 Create 查询,看起来像这样:
const faunadb = require('faunadb');
const q = faunadb.query;
const CreateFarm = (data) => (
q.Create(
q.Collection('farms'),
{ data },
)
);
正如我所说,这里的一切都按预期工作。当我试图开始规范化 FaunaDB 发回的数据时,麻烦就开始了。具体来说,我想将 Fauna 生成的 ID 合并到 data
对象中,然后将其与其他元数据的 none 一起发回。
我已经在使用其他资源这样做了,所以我编写了一个辅助查询并将其合并:
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
一起使用时,我最终在数据库中得到 两个 个相同的农场!
我花了很长时间查看应用程序的其余部分。肯定只有一个 POST
请求进来,而 CreateFarm
肯定只被调用一次。我最好的理论是,由于 Merge 复制了传递给它的第一个资源,Create
不知何故在数据库上被调用了两次。但是重新排序 Merge
调用不会改变任何东西。我什至尝试过先传入一个空对象,但最后总是创建两个相同的对象。
您的助手使用两个单独的 Create
表达式创建 FQL 查询。每个都被评估并创建一个新文档。这与 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 值,请将文档转换为尽可能接近应用程序中的那个点(例如使用 id 作为一组 Web 组件的键)。
There's even a slight Compute advantage for using Ref values rather than re-building Ref expressions from a Collection name and ID. The expression Ref(Collection("farms"), "1234")
counts as 2 FQL functions toward Compute costs, but reusing the Ref value returned by queries is free.
使用 GraphQL,_id
字段为您抽象出来,因为在 GraphQL 中使用文档类型会非常糟糕。但是,FQL 查询的最佳做法是尽可能直接使用 Ref。
不过,不要让我说绝对的话!我普遍认为任何事情都是有原因的。如果您认为您确实需要在文档数据中复制 ID,那么我会对为什么发表评论感兴趣。
在 Netlify 函数上使用带有 Node.js 运行 的 FaunaDB 时遇到一个奇怪的错误。
我正在建立一个快速的概念验证,最初一切正常。我有一个 Create 查询,看起来像这样:
const faunadb = require('faunadb');
const q = faunadb.query;
const CreateFarm = (data) => (
q.Create(
q.Collection('farms'),
{ data },
)
);
正如我所说,这里的一切都按预期工作。当我试图开始规范化 FaunaDB 发回的数据时,麻烦就开始了。具体来说,我想将 Fauna 生成的 ID 合并到 data
对象中,然后将其与其他元数据的 none 一起发回。
我已经在使用其他资源这样做了,所以我编写了一个辅助查询并将其合并:
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
一起使用时,我最终在数据库中得到 两个 个相同的农场!
我花了很长时间查看应用程序的其余部分。肯定只有一个 POST
请求进来,而 CreateFarm
肯定只被调用一次。我最好的理论是,由于 Merge 复制了传递给它的第一个资源,Create
不知何故在数据库上被调用了两次。但是重新排序 Merge
调用不会改变任何东西。我什至尝试过先传入一个空对象,但最后总是创建两个相同的对象。
您的助手使用两个单独的 Create
表达式创建 FQL 查询。每个都被评估并创建一个新文档。这与 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 值,请将文档转换为尽可能接近应用程序中的那个点(例如使用 id 作为一组 Web 组件的键)。
There's even a slight Compute advantage for using Ref values rather than re-building Ref expressions from a Collection name and ID. The expression
Ref(Collection("farms"), "1234")
counts as 2 FQL functions toward Compute costs, but reusing the Ref value returned by queries is free.
使用 GraphQL,_id
字段为您抽象出来,因为在 GraphQL 中使用文档类型会非常糟糕。但是,FQL 查询的最佳做法是尽可能直接使用 Ref。
不过,不要让我说绝对的话!我普遍认为任何事情都是有原因的。如果您认为您确实需要在文档数据中复制 ID,那么我会对为什么发表评论感兴趣。