如何替换 Fauna 中多对多关系中的所有连接

How to replace all connections in a many-to-many relationship in Fauna

假设我有这个架构:

Client {
 services: [Service] @relation(name: "ClientServices")
}
Service {
 clients: [Client] @relation(name: "ClientServices")
}

我想将一些服务连接到客户端,如下所示:

mutation {
 updateClient(id: ..., data : {
   services:  {
     connect: ["123", "456"] ## where there are valid service _id's
  }
 }) { ... }
}

太棒了。效果很好。 但是现在我想把所有的连接(服务)都换成其他的,但是还是保留123服务。

mutation {
 updateClient(id: ..., data : {
   services:  {
     connect: ["123", "789"] ## notice kept 123, and now want 789
  }
 }) { ... }
}

这将导致 Fauna 出现 instance not unique 错误。因为它试图连接 123 但它已经在 ClientServices 集合中(管理 m-m 关系的自动生成的集合。)

有没有一种简单的方法可以在没有 UDF 的情况下在一次通话中断开所有连接并重新连接我想要的连接?

至此,Fauna 已经创建、断开和连接。 您似乎在寻找 replace 自动计算差异并在断开连接和连接方面采取正确操作的方法。我认为目前纯 GraphQL 不可能做到这一点。您确实需要编写一个 UDF。对于其他人来说,它可能也是一个有趣的功能,因此它可能是论坛上功能请求的一个很好的候选者:https://forums.fauna.com/

我相信您可以在同一个突变中连接和断开连接(没有 UDF):

mutation {
 updateClient(id: ..., data : {
   services:  {
     connect: ["789"],
     disconnect: ["456"]
  }
 }) { ... }
}

这假定您有能力在客户端上计算差异。例如,使用 lodash:

const _filter = require('lodash/filter');
const _find = require('lodash/find');
const _map = require('lodash/map');

let orig = [{id: "123"}, {id: "456"}]
let replacements = [{id: "123"}, {id: "789"}]

let toConnect = _filter(replacements, o => !_find(orig, {id: o.id}))
let toDisconnect = _filter(orig, o => !_find(replacements, {id: o.id}))

mutate(
    // ...
    {
        connect: _map(toConnect, 'id'),
        disconnect: _map(toDisconnect, 'id')
    },
    // ...
)

作为提供 replace 功能的简单解决方案,也许 Fauna GQL API 可以围绕操作顺序提供一些保证。如果 disconnect 总是在 connect 之前执行,那么您总是可以断开 orig 并连接 replacements。这种保证似乎是合理的,因为我真的无法想象在同一个 API 调用中连接并立即断开关系的理智理由。