Third party GraphQL support for LeanCloud, running on LeanEngine
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
test
LICENSE
README.md
app.js
index.js
middleware.js
package.json
schema.js
server.js

README.md

LeanCloud GraphQL

运行在云引擎上的第三方 GraphQL 支持,允许你用 GraphQL 查询 LeanCloud 云存储中的所有数据。

部署到云引擎

LeanCloud 命令行工具

GraphQL

GraphQL 是 FaceBook 开源的一套查询语言,你可以用它定义数据的格式和获取方法(这就是 leancloud-graphql 做的工作,它会自动将你在 LeanCloud 的数据结构转换为 GraphQL 的 Schema),然后便可以在客户端以一种非常灵活的语法来获取数据,甚至也可以用它来创建和更新数据。

在使用 leancloud-graphql 之前,你可能需要先了解一下 GraphQL 的语法 ,下面我们不会过多地介绍 GraphQL 本身。这篇文章将使用 JavaScript SDK 文档中的 示例数据结构 进行讲解。

GraphQL 在客户端几乎不需要什么 SDK,你可以花几行代码封装一个工具函数:

function requestGraphQL(query) {
  return fetch('/', {
    method: 'POST',
    body: query
  }).then( res => {
    return res.json();
  }).then( result => {
    return result.data;
  });
}

我们也用 GraphiQL 提供了一个支持自动补全等功能的 GraphQL 控制台(本地调试时为 http://127.0.0.1:3000/),你可以在这里测试你的查询。

我们会应用客户端发来的 sessionToken,确保在用户的权限范围内进行查询。你可以从我们的 JavaScript SDK 上获取 sessionToken 并随着请求发送,修改 requestGraphQL:

  headers: {
    'Content-Type': 'application/graphql',
+   'X-LC-Session': AV.User.current() && AV.User.current().getSessionToken()
  },

获取数据

最简单的一个查询:

requestGraphQL(`
  query {
    Todo {
      title, priority
    }
  }
`)

默认会返回最多 100 条数据:

{
  Todo: [
    {title: "紧急 Bug 修复", priority: 0},
    {title: "打电话给 Peter",priority: 5},
    {title: "还信用卡账单", priority: 10},
    {title: "买酸奶", priority: 10},
    {title: "团队会议", priority: 5}
  ]
}

你可以在此基础上添加排序、条数限制等选项:

  • ascending 按照指定字段升序。
  • descending 按照指定字段降序。
  • limit 条数限制。

例如我们按照优先级升序排序,取最重要的两个任务:

query {
  Todo(ascending: priority, limit: 2) {
    title, priority
  }
}

结果:

{
  Todo: [
    {title: "紧急 Bug 修复", priority: 0},
    {title: "打电话给 Peter",priority: 5}
  ]
}

查询条件

首先你可以按照 objectId 进行简单的查询:

query {
  Todo(objectId: "5853a0e5128fe1006b5ce449") {
    title, priority
  }
}

结果:

{
  Todo: [
    {title: "还信用卡账单", priority: 10}
  ]
}

equalTo

你也可以像 LeanCloud 的 SDK 一样使用多种查询条件:

query {
  Todo(equalTo: {title: "团队会议"}) {
    title
  }
}

exists

exists 可以用来查询存在或不存在某一字段的对象,例如我们查询存在 title 但不存在 content 的 Todo:

query {
  Todo(exists: {title: true, content: false}) {
    title, content
  }
}

范围查询

query {
  Todo(greaterThanOrEqualTo: {priority: 10}) {
    title, priority
  }
}

目前支持的查询包括:

  • greaterThan 约束指定列大于特定值。
  • greaterThanOrEqualTo 约束指定列大于等于特定值。
  • lessThan 约束指定列小于特定值。
  • lessThanOrEqualTo 约束指定列小于等于特定值。

数组查询

query {
  Todo(containedIn: {tags: ["Online"]}) {
    title, tags
  }
}

目前支持的数组查询包括:

  • containedIn 约束指定列中包含特定元素。
  • containsAll 约束指定列中包含所有元素。

组合查询

你可以将我们前面提到的所有查询条件组合在一起:

query {
  Todo(exists: {content: true}, ascending: priority, greaterThan: {priority: 5}) {
    title, content, priority
  }
}

关系查询

Relation

如果对象的一个字段是 Relation,那么你就可以在 GraphQL 中将它展开,例如我们可以查询每个 TodoFolder 中包含的 Todo:

query {
  TodoFolder {
    name, containedTodos {
      title, priority
    }
  }
}

结果:

{
  TodoFolder: [{
    name: "工作",
    containedTodos: [
      {title: "紧急 Bug 修复", priority: 0},
      {title: "打电话给 Peter", priority: 5},
      {title: "团队会议", priority: 5}
    ]
  }, {
    name: "购物清单",
    containedTodos: [
      {title: "买酸奶", priority: 10}
    ]
  }]
}

Pointer

如果一个字段是 Pointer 你也可以将它展开,例如我们可以查询 Todo 的创建者(到用户表的指针):

query {
  Todo(limit: 1) {
    title, owner {
      username, email
    }
  }
}

结果:

{
  Todo: [
    {
      title: "紧急 Bug 修复",
      owner: {
        username: "someone",
        email: "test@example.com"
      }
    }
  ]
}

查询条件

你也可以在关系查询上附加查询参数或查询条件:

query {
  TodoFolder {
    name, containedTodos(limit: 1, exists: {content: true}) {
      title, content
    }
  }
}

结果:

{
  TodoFolder: [{
    name: "工作",
    containedTodos: [
      {title: "团队会议", content: "BearyChat"}
    ]
  }, {
    name: "购物清单",
    containedTodos: []
  }, {
    name: "someone",
    containedTodos: [
      {title: "还信用卡账单", content: "2016 年 12 月"}
    ]
  }]
}

支持的参数和条件包括:ascendingdescendinglimitobjectIdequalToexistsgreaterThangreaterThanOrEqualTolessThanlessThanOrEqualTocontainedIncontainsAll

反向关系

在实现一对多关系时,我们经常会在「多」上面保存一个到「一」的指针,leancloud-graphql 会自动在「多」上面创建一个属性,用来表示反向关系。例如因为 Todo 的 owner 是一个指向 _User 的 Pointer,所以 _User 上会自动出现一个 ownerOfTodo

query {
  _User {
    username, ownerOfTodo {
      title
    }
  }
}

这样我们便可以查到每个用户的 Todo:

{
  _User: [{
    username: "someone",
    ownerOfTodo: [
      {title: "紧急 Bug 修复"},
      {title: "打电话给 Peter"},
      {title: "还信用卡账单"},
      {title: "买酸奶"}
    ]
  }]
}

你也可以在 Relation 上进行反向查询,例如查询每个 Todo 所属的 TodoFolder:

query {
  Todo {
    title, containedTodosOfTodoFolder {
      name
    }
  }
}

结果(省略了一部分):

{
  Todo: [{
    title: "紧急 Bug 修复",
    containedTodosOfTodoFolder: [
      {name: "工作"},
      {name: "someone"}
    ]
  }, {
    title: "买酸奶",
    containedTodosOfTodoFolder: [
      {name: "购物清单"},
      {name: "someone"}
    ]
  }, {
    title: "团队会议",
    containedTodosOfTodoFolder: [
      {name: "工作"}
    ]
  }]
}

多级关系

在 GraphQL 中你甚至可以进行多层级的关系查询:

query {
  TodoFolder {
    name,
    containedTodos {
      title, owner {
        username, email
      }
    }
  }
}

结果(省略了一部分):

{
  TodoFolder: [{
    name: "工作",
    containedTodos: [{
      title: "紧急 Bug 修复",
      owner: {
        username: "someone",
        email: "test@example.com"
      }
    }, // ...
    ]
  }, // ...
  ]
}

修改对象

GraphQL 毕竟是一个数据查询语言,因此我们仅提供了非常有限的创建和更新对象的功能。

创建对象

你可以这样创建一个对象,并要求服务器返回 objectId、标题和优先级:

mutation {
  Todo(title: "思考巨石阵是如何修建的") {
    objectId, title, priority
  }
}

结果:

{
  Todo: {
    objectId: "5853adb7b123db006562f83b",
    title: "思考巨石阵是如何修建的",
    priority: 10
  }
}

更新对象

然后你可以用非常相似的语法来更新这个对象(当你提供了 objectId 便是更新对象):

mutation {
  Todo(objectId: "5853adb7b123db006562f83b", priority: 5) {
    title, priority
  }
}

结果:

{
  Todo: {
    title: "思考巨石阵是如何修建的",
    priority: 5
  }
}

添加到现有项目

如果要添加到现有项目,需要先将 leancloud-graphql 添加为依赖:

npm install --save leancloud-graphql

请确保 Node.js 版本在 4.0 以上。

作为中间件添加

leancloud-graphql 导出了一个 express 中间件,可以直接添加到现有的 express 项目上:

var leancloudGraphQL = require('leancloud-graphql').express;
var app = express();
app.use('/graphql', leancloudGraphQL());

leancloudGraphQL 有一些选项:

  • graphiql 开启调试控制台,默认 true.
  • cors 提供跨域支持,默认 true.
  • pretty 格式化返回的 JSON。

使用该中间件时请确保环境变量中有 LEANCLOUD_ 系列的环境变量,即需要运行在云引擎上或用 lean up 启动。

获取 GraphQLSchema

leancloud-graphql 默认导出了一个构建 GraphQLSchema 的函数:

var buildSchema = require('leancloud-graphql');
var {printSchema} = require('graphql');

buildSchema({
  appId: process.env.LEANCLOUD_APP_ID,
  appKey: process.env.LEANCLOUD_APP_KEY,
  masterKey: process.env.LEANCLOUD_APP_MASTER_KEY
}).then( schema => {
  console.log(printSchema(schema));
});