图谱 API 的使用方法

图谱 API 概览中包含图谱 API 术语和结构等基本信息。本文将详细介绍您可以使用图谱 API 执行的各种操作。

HTTP/1.1

所有数据传输都必须遵守 HTTP/1.1 协议,所有端点都需要使用 HTTPS。我们还对 facebook.com 启用了 includeSubdomains HSTS 指令,但这不会对您的图谱 API 调用产生不利影响。

托管网址

几乎所有的请求都会传递到 graph.facebook.com 托管网址。唯一的例外是视频上传请求,这类请求会使用 graph-video.facebook.com

访问口令

借助访问口令,您的应用可以访问图谱 API。访问口令通常具备以下两个功能:

  • 允许应用访问用户信息,无需用户密码;
  • 让系统能识别应用、使用应用的用户,以及用户允许应用访问的数据类型。

所有图谱 API 端点都要求使用特定类型的访问口令,因此每次访问端点时,您的请求必须包含一个访问口令。

访问口令的工作原理

访问口令遵循 OAuth 2.0 协议。OAuth 2.0 允许用户或主页等实体授予访问口令。通常,这一过程通过网页界面完成。被授予访问口令后,应用便可以使用这些口令访问特定的信息。

例如,此应用要求用户向其授予照片、视频和电子邮箱的访问权限:

正如您看到的一样,这是 Facebook 界面。用户刚刚通过相关界面登录了他们的帐户,这让我们验证了用户身份。如果用户继续,我们会使用旧口令(应用口令)交换得到一个新口令(用户口令)。之后,应用可以使用新的用户口令发出图谱 API 请求,但只能访问特定用户的照片、视频和电子邮箱。

这是访问口令的重要属性。与其他信息一样,应用编号和用户编号都已编码到口令中,我们会使用这些编号追踪用户允许应用访问哪些数据。举例而言,如果您在用户授予权限后检查口令,其中会包含下列信息:

由于口令允许访问用户数据、可由任何人使用,并且非常重要,因此在查询请求中使用口令时应采取预防措施进行保护。保护口令最简单的方式是使用 Facebook 登录功能来处理您的口令。

Facebook 登录

OAuth 2.0 涉及太多跳转、登录提示和口令交换,所以为了打造更简单的体验,我们推出了 Facebook 登录产品。Facebook 登录产品的功能和方法易于使用,适用于我们所有的 SDK。相比构建专属解决方案,此产品让访问口令使用更加简单。

如需了解更多有关访问口令和 Facebook 登录的信息,或详细了解如何构建自己的解决方案,请参阅我们的 Facebook 登录文档

读取

节点

大部分读取操作都始终通过节点开始。节点是指拥有唯一编号的个体对象。主页节点对象有很多,每个节点对象都有一个唯一的编号,例如 Coca-Cola 主页拥有唯一编号 820882001277849。要读取任何节点,您需要查询特定对象的编号。因此,要读取 Coca-Cola 主页节点,您应该查询其编号:

GET https://graph.facebook.com/820882001277849

此请求会默认以 JSON 格式返回下列字段(节点属性):

{
  "name": "Coca-Cola",
  "id": "820882001277849"
}

连线

节点有连线,连线通常可以返回与某节点关联的其他节点的集合。要读取连线,您必须在路径中提供节点编号和连线名称。例如,/page 节点有 /feed 连线,此连线可以返回与主页关联的所有帖子节点。下面的示例展示了如何使用连线获取与 Coca-Cola 主页关联的所有帖子:

GET https://graph.facebook.com/820882001277849/feed

JSON 响应结果将如下所示:

{
  "data": [
    {
      "created_time": "2017-12-08T01:08:57+0000",
      "message": "Love this puzzle. One of my four coke puzzles",
      "id": "820882001277849_1805191182846921"
    },
    {
      "created_time": "2017-12-07T20:06:14+0000",
      "message": "You need to add grape as a flavor for Coke in your freestyle machines.",
      "id": "820882001277849_1804966026202770"
    },
    {
      "created_time": "2017-12-07T01:29:12+0000",
      "message": "Plz play the old commercial’s with the polar bears. Would be nice to see them this holiday",
      "id": "820882001277849_1804168469615859"
    }
  ]
}

请注意,响应不仅包含集合中帖子节点的编号,还包含 created_timemessage 字段。这是常见情况。大部分连线都会默认包含一个或多个字段。

字段

字段是节点属性。查询节点时,系统会默认返回一系列字段,如上面的示例所示。您可以使用 fields 参数并列出需要的每个字段,来指定希望返回的字段。这会覆盖默认设置,仅返回您指定的字段,但系统会始终返回对象编号。

例如,主页节点参考文档列出了您在读取主页节点时可以查询的字段。如果您想获得 Coca-Cola 主页的 aboutfan_countwebsite 字段,可以发出如下请求:

GET https://graph.facebook.com/820882001277849
    ?fields=about,fan_count,website

这会返回以下响应:

{
  "about": "Welcome to the happiest Facebook page on, um, Facebook.",
  "fan_count": 106714402,
  "website": "http://coca-cola.com",
  "id": "820882001277849"
}

通常返回对象集合的连线也会返回集合中每个对象的相关字段。假设您使用 /photos 连线获取与 Coca-Cola 主页相关的所有照片节点:

GET https://graph.facebook.com/820882001277849/photos

这会生成如下所示的响应:

{
  "data": [
    {
      "created_time": "2016-08-23T13:12:10+0000",
      "id": "1308573619175349"
    },
    {
      "created_time": "2016-08-05T22:34:19+0000",
      "id": "1294456907253687"
    },
    {
      "created_time": "2016-04-29T16:17:02+0000",
      "id": "1228552183844160"
    }
  ]
}

正如您看到的一样,/photos 连线会默认返回一个集合,其中包含照片节点编号以及每张照片的 created_time 属性。与节点一样,您可以使用 fields 参数为集合中返回的每个对象指定您希望返回的字段。

例如,如果想要获取 /photos 连线返回的每个照片节点的 heightwidthlink(网址)字段:

GET https://graph.facebook.com/820882001277849/photos
      ?fields=height,width,link

响应如下所示:

{
  "data": [
    {
      "height": 720,
      "width": 720,
      "link": "https://www.facebook.com/CocaColaUnitedStates/photos/a.820887414610641.1073741825.820882001277849/1308573619175349/?type=3",
      "id": "1308573619175349"
    },
    {
      "height": 720,
      "width": 720,
      "link": "https://www.facebook.com/CocaColaUnitedStates/photos/a.820887414610641.1073741825.820882001277849/1294456907253687/?type=3",
      "id": "1294456907253687"
    },
    {
      "height": 180,
      "width": 180,
      "link": "https://www.facebook.com/CocaColaUnitedStates/photos/a.820887414610641.1073741825.820882001277849/1228552183844160/?type=3",
      "id": "1228552183844160"
    }
  ]
}

请注意,您也可以使用 fields 参数指定连线,这非常适用于使用字段扩展的情况。

字段扩展

如果您使用图谱 API 探索工具测试上述 GET /page/photos 查询,可能会发现请求返回的对象超出三个,还将结果分页显示。这对于大部分连线来说都很常见。下面即将介绍如何遍历结果,但现在,我们先来看看字段扩展。借助字段扩展,您不仅可以执行嵌套查询,还可以限制结果数量并对结果进行排序

限制结果数量

通过限制操作,您可以控制每组分页结果中返回的对象数量。要限制结果数量,请向任意字段或连线添加 .limit() 变量。

例如,对 Coca-Cola 主页的 /feed 连线执行 GET 请求,可能会返回数百篇帖子。您可以通过如下操作来限制每个结果页返回的帖子数量:

GET https://graph.facebook.com/820882001277849
    ?fields=feed.limit(3)

这会返回与 Coca-Cola 主页关联的所有帖子,但会将每个结果页中的对象数量限制为 3 个。请注意,建议不要在路径网址中指定动态连线 (/page/feed),而是在 fields 参数 (?fields=feed) 中指定此连线,这样您可以附加 .limit(3) 变量。

下面是查询结果:

{
  "feed": {
    "data": [
      {
        "created_time": "2017-12-12T01:24:21+0000",
        "message": "This picture of my grandson with Santa screams Coca Cola",
        "id": "820882001277849_1809387339093972"
      },
      {
        "created_time": "2017-12-11T23:40:17+0000",
        "message": ":)",
        "id": "820882001277849_1809316002434439"
      },
      {
        "created_time": "2017-12-11T23:31:38+0000",
        "message": "Thought you might enjoy this.  My horse loves Coke!",
        "id": "820882001277849_1809310929101613"
      }
    ],
    "paging": {
      "cursors": {
        "before": "Q2c4U1pXNTBYM0YxWlhKNVgzTjBiM0o1WDJsa0R5UTRNakE0T0RJd01ERXlOemM0TkRrNkxUVXdPRE16TXpVM01EQXpNVFUwTkRRME5Ua1BER0ZA3YVY5emRHOXllVjlwWkE4ZA09ESXdPRGd5TURBeE1qYzNPRFE1WHpFNE1Ea3pPRGN6TXprd09UTTVOeklQQkhScGJXVUdXaTh2eFFFPQZDZD",
        "after": "Q2c4U1pXNTBYM0YxWlhKNVgzTjBiM0o1WDJsa0R5TTRNakE0T0RJd01ERXlOemM0TkRrNk1UTTJORE01T0RVNU1UZAzVPRGMyTnpFNE1BOE1ZAWEJwWDNOMGIzSjVYMmxrRHlBNE1qQTRPREl3TURFeU56YzRORGxmTVRnd09USXdOamsxTlRjM09EWTNOdzhFZAEdsdFpRWmFMdk9HQVE9PQZDZD"
      },
      "next": "https://graph.facebook.com/820882001277849/feed?access_token=valid_token_goes_here"
    }
  },
  "id": "820882001277849"
}

正如您看到的一样,此结果分页只显示三个对象,但响应包含 next 字段和网址,您可以通过这个网址获取下一页结果。

为结果排序

您可以根据对象创建时间为结果排序。为此,您可以对字段或连线结合使用 .order() 变量和下列值之一。

  • chronological — 对结果排序,最早创建的对象排第一。
  • reverse_chronological — 对结果排序,最新创建的对象排第一。

例如,获取 Coca-Cola 主页上的视频帖子 (1809938745705498) 的所有评论,按照时间先后顺序(最早创建的对象排第一)对结果排序,并将每个结果页显示的对象数量限制为三个:

GET https://graph.facebook.com/1809938745705498
    ?fields=comments.order(chronological).limit(3)

请再次注意,为了对连线使用变量,您必须在 fields 参数中指定连线。正如所看到的一样,您可以对单个字段或连线结合使用 .limit().order() 变量。

结果如下:

{
  "comments": {
    "data": [
      {
        "created_time": "2017-12-12T14:12:20+0000",
        "message": ":) :) :)",
        "id": "1809938745705498_1809939942372045"
      },
      {
        "created_time": "2017-12-12T14:14:03+0000",
        "message": "seasons greetings!",
        "id": "1809938745705498_1809941802371859"
      },
      {
        "created_time": "2017-12-12T14:14:11+0000",
        "message": "My bestie <3",
        "id": "1809938745705498_1809941879038518"
      }
    ],
    "paging": {
      "cursors": {
        "before": "WTI5dGJXVnVkRjlqZAFhKemIzSTZANVGd3T1Rrek9UZAzROVGN3TlRNNE5Eb3hOVEV6TURnM09UTTIZD",
        "after": "WTI5dGJXVnVkRjlqZAFhKemIzSTZANVGd4TURBd09UazROVFk1T0RNM05Eb3hOVEV6TURreU5qQXoZD"
      },
      "next": "https://graph.facebook.com/1809938745705498/comments?access_token=valid_token_goes_here"
    }
  },
  "id": "1809938745705498"
}

发布

大部分连线都允许您向节点集合发布对象。您可以通过对节点的连线发送 POST 请求来实现这一操作。例如,您可以使用照片节点的 /comments 连线对照片发布评论:

POST https://graph.facebook.com
  /1809938745705498
    /comments
      ?message=Awesome!

成功后,大部分连线都会返回您刚刚发布的对象的编号,这通常是接受发布操作的对象的编号与新编号字符串的组合:

{
  "id": "1809938745705498_1810399758992730"
}

一般来说,发布操作需要额外的权限,所以请参阅每个连线的参考文档,确定各个连线需要的权限。

用于发布对象的访问口令可能会影响对象的显示效果。 如果使用的是主页访问口令,则会显示该对象由主页发布;如果使用用户访问口令,则会显示该对象由用户发布。

许多连线还支持高级功能,如先写入后读取(您可以通过这一功能立即读取新发布的对象)和批量发布(您可以通过这一功能批量执行一系列发布操作)。

更新

您可以使用 POST 请求对当前节点执行更新操作。例如,要更新当前评论的 message 字段,您可以发出下列请求:

POST https://graph.facebook.com
  /1809938745705498_1810399758992730
    ?message=Happy%20Holidays!

成功后,节点将返回 success 字段和值 true

{
  "success": true
}

与发布操作一样,更新操作也需要额外的权限,这些权限列于每个节点的参考文档中。与大部分连线一样,许多节点都支持先写入后读取功能。

删除

一般来说,您可以使用 DELETE 操作删除节点:

DELETE https://graph.facebook.com
  /1809938745705498_1810399758992730

成功后,节点将返回 success 字段和值 true

{
  "success": true
}

您通常可以只删除自己创建的节点,但建议您参阅每个节点的参考指南,了解关于删除操作的要求。

如果客户端不支持所有 HTTP 方法,为支持这类客户端,您可以向节点发送 POST 请求,并添加 method=delete 参数和值,以覆盖 HTTP 方法:

POST https://graph.facebook.com
  /1809938745705498_1810399758992730
    ?method=delete

遍历分页结果

当您向节点或连线发出 API 请求时,通常不会在单个响应中收到该请求的全部结果。这是因为某些响应可能包含数千个对象,因此大多数响应都将默认分页。

基于游标的分页

基于游标的分页是最有效的分页方法,应尽量使用这种方法。游标是指标记数据列表中特定项目的一个随机字符串。该项目未被删除时,游标将始终指向列表的相同部分,项目被删除时游标即失效。因此,您的应用不应存储游标,也不能假定它们在未来有效。

读取支持游标分页的连线时,您将看到以下 JSON 响应:

{
  "data": [
     ... Endpoint data is here
  ],
  "paging": {
    "cursors": {
      "after": "MTAxNTExOTQ1MjAwNzI5NDE=",
      "before": "NDMyNzQyODI3OTQw"
    },
    "previous": "https://graph.facebook.com/me/albums?limit=25&before=NDMyNzQyODI3OTQw"
    "next": "https://graph.facebook.com/me/albums?limit=25&after=MTAxNTExOTQ1MjAwNzI5NDE="
  }
}

游标分页的连线支持以下参数:

  • before:这是指向已返回的数据页面开头的游标。
  • after:这是指向已返回的数据页面末尾的游标。
  • limit:这是可能返回的最大对象数量。由于应用了筛选条件,查询操作返回的值可能低于 limit 值。不要依赖小于 limit 值的结果数来指明您的查询到达数据列表的末尾,请使用下面描述的不包含 next 的方式来指明到达数据列表的末尾。例如,如果您将 limit 设置为 10 但返回 9 个结果,则可能有更多数据可用,但是有一个项目由于隐私筛选条件而被删除。 为提升性能,也可为某些连线设置最大的 limit 值。所有情况下,API 都将返回正确的分页链接。
  • next:将返回下一页数据的图谱 API 端点。如果未包含,则显示的是最后一页数据。根据分页的可见性和隐私,页面可能为空,但包含“next”分页链接。“next”链接不再出现时,应停止分页。
  • previous:将返回上一页数据的图谱 API 端点。如果未包含,则显示的是第一页数据。

请勿存储游标。如果添加或删除了项目,游标可能很快就会失效。

基于时间的分页

时间分页使用指向数据列表中的特定时间的 Unix 时间戳在结果数据中导航。

使用采用时间分页的端点时,您将看到以下 JSON 响应:

{
  "data": [
     ... Endpoint data is here
  ],
  "paging": {
    "previous": "https://graph.facebook.com/me/feed?limit=25&since=1364849754",
    "next": "https://graph.facebook.com/me/feed?limit=25&until=1364587774"
  }
}

基于时间的连线支持以下参数:

  • until:指向基于时间的数据范围末尾的 Unix 时间戳或 strtotime 数据值。
  • since:指向基于时间的数据范围开头的 Unix 时间戳或 strtotime 数据值。
  • limit:这是可能返回的最大对象数量。由于应用了筛选条件,查询操作返回的值可能低于 limit 值。不要依赖小于 limit 值的结果数来指明您的查询到达数据列表的末尾,请使用下面描述的不包含 next 的方式来指明到达数据列表的末尾。例如,如果您将 limit 设置为 10 但返回 9 个结果,则可能有更多数据可用,但是有一个项目由于隐私筛选条件而被删除。 为提升性能,也可为某些连线设置最大的 limit 值。所有情况下,API 都将返回正确的分页链接。
  • next:将返回下一页数据的图谱 API 端点。
  • previous:将返回上一页数据的图谱 API 端点。

要获得一致的结果,需要指定 sinceuntil 参数。此外,建议时间差异最大为 6 个月。

基于偏移的分页

如果时间顺序对您不重要,只需要返回特定数量的对象,则可以使用偏移分页。只有连线不支持基于游标或时间的分页时,才能使用这种分页方法。

基于偏移分页的连线支持以下参数:

  • offset:这将按指定的数字偏移每个页面的开头。
  • limit:这是可能返回的最大对象数量。由于应用了筛选条件,查询操作返回的值可能低于 limit 值。不要依赖小于 limit 值的结果数来指明您的查询到达数据列表的末尾,请使用下面描述的不包含 next 的方式来指明到达数据列表的末尾。例如,如果您将 limit 设置为 10 但返回 9 个结果,则可能有更多数据可用,但是有一个项目由于隐私筛选条件而被删除。 为提升性能,也可为某些连线设置最大的 limit 值。所有情况下,API 都将返回正确的分页链接。
  • next:将返回下一页数据的图谱 API 端点。如果未包含,则显示的是最后一页数据。根据分页的可见性和隐私,页面可能为空,但包含“next”分页链接。“next”链接不再出现时,应停止分页。
  • previous:将返回上一页数据的图谱 API 端点。如果未包含,则显示的是第一页数据。

请注意,如果正分页的项目列表添加了新的对象,每个基于偏移的页面的内容都将发生更改。

并非所有 API 调用都支持基于偏移的分页。要获得一致的结果,建议您使用我们在响应中返回的 previous/next 链接分页。