首页 > 解决方案 > 如何在 FaunaDB 中使用 UDF 循环输入数组?

问题描述

我有一个关于映射 ID 数组(输入数据)并将所有相关文档返回到这些 ID 的问题。我设置了一个 UDF 来检索单个 ID 的文档,并希望通过一些调整来实现这一点。我似乎无法弄清楚如何映射输入数据并创建一个变量 (data:) 来存储新的文档数组。任何帮助表示赞赏。这是有效的单条目UDF:

Query(
  Lambda(
    ["inputdata"],
    Let(
      {
        data: Map(
          Paginate(
            Match(
              Index("certificate_by_dealer"),
              Ref(Collection("Dealers"), Select("dealer", Var("inputdata")))
            )
          ),
          Lambda(["ref"], Get(Var("ref")))
        )
      },
      Select(["data"], Var("data"))
    )
  )
)

是否有一个简单的...或任何解决方案可以使 ID 数组作为输入数据工作?

调用函数为:

Call("user_dealers_all_certificates", {
  ids: [301393590798516736, 301393590798516749]
}

不幸的是,我没有得到任何结果。(添加引号解决了这个问题)

这是实施建议的UDF:

Query(
  Lambda(
    ["inputdata"],
    Let(
      { dataIds: Select("ids", Var("inputdata")) },
      Union(
        Map(
          Var("dataIds"),
          Lambda(
            ["id"],
            Select(
              ["data"],
              Paginate(
                Match(
                  Index("certificate_by_dealer"),
                  Ref(Collection("Dealers"), Var("id"))
                )
              )
            )
          )
        )
      )
    )
  )
)

添加引号创建了正确的响应:

Call("user_dealers_all_certificates", {ids: ["302122229239382536", "301394099049595400"]})

[
  Ref(Collection("Certificate"), "302122488174739977"),
  Ref(Collection("Certificate"), "302120872550859273")
]

但是 GraphQL 查询返回错误数据:

query {
  allUserDealersCertificate(data: {ids: ["302122229239382536", "301394099049595400"]}){
   data {
_id
  }
}
}

回复:

{
  "errors": [
    {
      "message": "Lambda expects an array with 1 elements. Array contains 4.",
      "extensions": {
        "code": "invalid argument"
      }
    }
  ]
}

没有分页的 GraphQL 错误:模式中为真:

{
  "data": {
    "allUserDealersCertificate": [
      null,
      null
    ]
  },
  "errors": [
    {
      "message": "Cannot return null for non-nullable type (line 3, column 5):\n    _id\n    ^",
      "path": [
        "allUserDealersCertificate",
        0,
        "_id"
      ],
      "locations": [
        {
          "line": 3,
          "column": 5
        }
      ]
    },
    {
      "message": "Cannot return null for non-nullable type (line 3, column 5):\n    _id\n    ^",
      "path": [
        "allUserDealersCertificate",
        1,
        "_id"
      ],
      "locations": [
        {
          "line": 3,
          "column": 5
        }
      ]
    }
  ]
}

标签: user-defined-functionsfacebook-fqlfaunadb

解决方案


根据您提供的查询,我觉得有必要指出该Match函数执行完全匹配。它不会(也不能)为您展开结构化数组。该功能也不能Ref

您需要调用Map,inputdata并获取每个 id 的结果。然后,您可以将Union这些结果合并到一个列表中。

我不知道您正在处理的数据的确切形状,所以这里有一个与仪表板中可用的预填充数据一起使用的查询:

Let(
  {
    // the pre-populated data has 3 stores, with ids 301, 302, and 303
    // here, we want the products in stores 301 and 302
    ids: [ 301, 302 ]
  },
  // this is where we combine all of the results
  Union(
    Map(
      // here is where we loop over the list of ids
      Var("ids"),
      Lambda(
        // for each id, run this function's expression
        "id",
        Select(
          // each Paginate call returns a page of results with its own data
          // field, so we have to select those out
          "data",
          Paginate(
            Match(
              Index("products_by_store"),
              // here we compose a reference to a specific store, using the
              // Lambda function's current id
              Ref(Collection("stores"), Var("id"))
            )
          )
        )
      )
    )
  )
)

我用来Let模拟将数组传递到 UDF 主体的 Npte。运行此查询时,结果应为:

[
  ["avocados", "Conventional Hass, 4ct bag", 3.99],
  ["cilantro", "Organic, 1 bunch", 1.49],
  ["limes", "Conventional, 1 ct", 0.35],
  ["limes", "Organic, 16 oz bag", 3.49],
  ["cups", "Translucent 9 Oz, 100 ct", 6.98],
  ["pinata", "Giant Taco Pinata", 23.99],
  ["pinata", "Original Classic Donkey Pinata", 24.99]
]

推荐阅读