数组字段上的 GraphQL 过滤

GraphQL filtering on array field

我有一份文件,内容如下:

{
  "data": {
    "posts": [
      {
        "id": "5d9f1af799785458ed55fcf3",
        "title": "Lorem ipsum dolor sit amet, consectetuer adipiscing eli",
        "likedBy": {
          "readers": [
            "abc",
            "xyz",
            "mnp"
          ]
        }
      },
      {
        "id": "5d9f2afa9cf1b45a20edaf93",
        "title": "Sed ut perspiciatis unde omnis iste natus error sit volupt",
        "likedBy": null
      },
      {
        "id": "5d9f2d1cd12ce45b11e90920",
        "title": "But I must explain to you how all this mistaken idea of deno",
        "likedBy": null
      }
    ]
  }
}

在这里,我有一个字段 likedBy,它是一个以数组为值的对象。

现在,我可以运行以下查询来检索所有文档:

{
  posts{
    id
    title
    likedBy
  }
}

但是,有什么方法可以在查询级别过滤掉数组的特定值吗?例如,假设我希望输出如下所示:

{
  "data": {
    "posts": [
      {
        "id": "5d9f1af799785458ed55fcf3",
        "title": "Lorem ipsum dolor sit amet, consectetuer adipiscing eli",
        "likedBy": {
          "readers": [
            "abc",
          ]
        }
      },
      {
        "id": "5d9f2afa9cf1b45a20edaf93",
        "title": "Sed ut perspiciatis unde omnis iste natus error sit volupt",
        "likedBy": null
      },
      {
        "id": "5d9f2d1cd12ce45b11e90920",
        "title": "But I must explain to you how all this mistaken idea of deno",
        "likedBy": null
      }
    ]
  }
}

在这里,我像以前一样返回了所有文档,除了 likedBy 数组中只有 abc。使用 GraphQL 可以吗?

是的,你可以。您可以在 graphql resolver 函数中实现过滤。即使您不使用 Apollo Server 来 运行 您的 graphql 服务器,link 到 the Apollo Server graphql resolver 也应该有所帮助。

如果您想通过名称是否以字母 "a" 开头来过滤 reader,即 "abc",它可能看起来像这样。我正在使用 SQL 查询来说明数据获取(例如 SELECT * FROM db_table),但您可以用任何方法替换它以从数据源(数据库,excel 文件、文档数据库等.)

// 您的查询

query($startsWith: String) {
  posts{
    id
    title
    likedBy(startsWith: $startsWith) {
       readers
    }
  }
}

// 您随查询发送的变量/输入参数

{
   "startsWith": "a"
}

// 您可能编写的解析器函数可以按 reader 的第一个字母表(或任何其他条件)进行过滤

const resolvers = {
   Query: {
      posts: function(root, args, context, info) {
         return context.db.query('SELECT * FROM posts')
      },
   },
   Posts: {
      id: function(parent, args, context, info){
         return parent.id // posts is the parent
      },
      title: function(parent, args, context, info){
         return parent.title
      },
      likedBy: function(parent, args, context, info){
         const postId = parent.id;

         const targetAlphabet = args.startsWith; // <= This is where your input ends up

         const allReadersWhoLikeThisPost = context.db.query(`SELECT DISTINCT * FROM readerLikes rl WHERE rl.liked_post_id = ${postId}`, 'collection')

         const readerNames = allReadersWhoLikeThisPost.map(reader => reader.name)

         // Filter for readers whose name starts with "a"
         const filteredReaderNames = readerNames.filter(name => name.substring(0,1) === targetAlphabet) 

         const reshapedData = {
             readers: filteredReaderNames
         }
         return reshapedData;
      }
   },

}