REST API:过滤器

页面摘要: REST API 的过滤(filters)功能可使用 $eq、$contains、$between 等运算符对查询结果进行过滤,支持使用 $and、$or、$not 进行复杂过滤,以及跨关联内容的深层过滤(deep filtering)。

REST API 提供了对通过 "Get entries" 方法获取的结果进行过滤的能力。

使用 Strapi 的可选功能可提供更多的过滤器:

  • 若在某个 content-type 上启用了 国际化(i18n)插件,则可以按区域(locale)进行过滤。
  • 若启用了 草稿与发布,则可以根据 published(默认)或 draft 状态进行过滤。
TIP

Strapi 利用 qs 库 解析嵌套对象的能力来创建更复杂的查询。

使用 qs 直接生成复杂查询,而不是手动创建。本文档中的示例展示了如何使用 qs。

如果你更喜欢使用在线工具而不是在本地用 qs 生成查询,也可以使用交互式查询构建器。

查询可以接受一个 filters 参数,语法如下:

GET /api/:pluralApiId?filters[field][operator]=value

可用的运算符如下:

运算符说明
$eq等于
$eqi等于(不区分大小写)
$ne不等于
$nei不等于(不区分大小写)
$lt小于
$lte小于或等于
$gt大于
$gte大于或等于
$in包含在数组中
$notIn不包含在数组中
$contains包含
$notContains不包含
$containsi包含(不区分大小写)
$notContainsi不包含(不区分大小写)
$null为 null
$notNull不为 null
$between介于…之间
$startsWith以…开头
$startsWithi以…开头(不区分大小写)
$endsWith以…结尾
$endsWithi以…结尾(不区分大小写)
$or以「或」表达式连接过滤器
$and以「与」表达式连接过滤器
$not以「非」表达式连接过滤器

当在 filters 对象中传入多个字段时,它们会隐式地使用 $and 连接(例如 GET /api/restaurants?filters[stars][$gte]=3&filters[open][$eq]=true 仅返回营业中且至少有 3 颗星的餐馆)。

TIP

$and、$or 与 $not 运算符可以相互嵌套。

WARNING

默认情况下,过滤器只能用于由 Content-type Builder 与 CLI 生成的 find 接口(endpoints)。

示例:查找名字为 'John' 的用户

使用 $eq 过滤运算符进行精确匹配。

cURL

curl 'http://localhost:1337/api/users?filters[username][$eq]=John' \
  -H 'Authorization: Bearer <token>'

JavaScript

const qs = require('qs');
const query = qs.stringify({
  filters: {
    username: {
      $eq: 'John',
    },
  },
}, {
  encodeValuesOnly: true, // 美化 URL
});

await request(`/api/users?${query}`);

响应

{
  "data": [
    {
      "id": 1,
      "documentId": "znrlzntu9ei5onjvwfaalu2v",
      "username": "John",
      "email": "john@test.com",
      "provider": "local",
      "confirmed": true,
      "blocked": false,
      "createdAt": "2021-12-03T20:08:17.740Z",
      "updatedAt": "2021-12-03T20:08:17.740Z"
    }
  ],
  "meta": {
    "pagination": {
      "page": 1,
      "pageSize": 25,
      "pageCount": 1,
      "total": 1
    }
  }
}

示例:查找 id 为 3、6、8 的多家餐馆

使用 $in 过滤运算符配合值数组,查找多个精确值。

cURL

curl 'http://localhost:1337/api/restaurants?filters[id][$in][0]=3&filters[id][$in][1]=6&filters[id][$in][2]=8' \
  -H 'Authorization: Bearer <token>'

JavaScript

const qs = require('qs');
const query = qs.stringify({
  filters: {
    id: {
      $in: [3, 6, 8],
    },
  },
}, {
  encodeValuesOnly: true, // 美化 URL
});

await request(`/api/restaurants?${query}`);

响应

{
  "data": [
    {
      "id": 3,
      "documentId": "ethwxjxtvuxl89jq720e38uk",
      "name": "test3"
    },
    {
      "id": 6,
      "documentId": "ethwxjxtvuxl89jq720e38uk",
      "name": "test6"
    },
    {
      "id": 8,
      "documentId": "cf07g1dbusqr8mzmlbqvlegx",
      "name": "test8"
    }
  ],
  "meta": {}
}

复杂过滤(Complex filtering)

组合 $and 与 $or 运算符进行复杂过滤。

cURL

curl 'http://localhost:1337/api/books?filters[$and][0][$or][0][date][$eq]=2020-01-01&filters[$and][0][$or][1][date][$eq]=2020-01-02&filters[$and][1][author][name][$eq]=Kai%20doe' \
  -H 'Authorization: Bearer <token>'

JavaScript

const qs = require('qs');
const query = qs.stringify({
  filters: {
    $and: [
      {
        $or: [
          {
            date: {
              $eq: '2020-01-01',
            },
          },
          {
            date: {
              $eq: '2020-01-02',
            },
          },
        ],
      },
      {
        author: {
          name: {
            $eq: 'Kai doe',
          },
        },
      },
    ],
  },
}, {
  encodeValuesOnly: true, // 美化 URL
});

await request(`/api/books?${query}`);

响应

{
  "data": [
    {
      "id": 1,
      "documentId": "rxngxzclq0zdaqtvz67hj38d",
      "name": "test1",
      "date": "2020-01-01"
    },
    {
      "id": 2,
      "documentId": "kjkhff4e269a50b4vi16stst",
      "name": "test2",
      "date": "2020-01-02"
    }
  ],
  "meta": {}
}
NOTE

上面的响应只包含图书自身的属性。除非通过 populate 参数 显式请求(例如在请求中加上 &populate=author),否则由 $and 过滤器所遍历的 author 关联不会被返回。

深层过滤(Deep filtering)

NOTE
  • 关联、媒体字段、组件与动态区域默认不会被联表加载(populate)。使用 populate 参数来加载这些内容结构(参见 populate 文档)
  • 你可以过滤所联表加载的内容,也可以过滤嵌套关联,但无法对多态内容结构(如媒体字段与动态区域)使用过滤器。
WARNING

使用深层过滤器查询 API 可能会导致性能问题。如果你的某个深层过滤查询过慢,建议构建一个自定义路由(custom route)并采用优化后的查询版本。

使用各类 API 进行深度过滤

如需各类 API 深度过滤的示例,请参阅这篇博客文章。

使用深层过滤对关联字段进行过滤。

cURL

curl 'http://localhost:1337/api/restaurants?filters[chef][restaurants][stars][$eq]=5' \
  -H 'Authorization: Bearer <token>'

JavaScript

const qs = require('qs');
const query = qs.stringify({
  filters: {
    chef: {
      restaurants: {
        stars: {
          $eq: 5,
        },
      },
    },
  },
}, {
  encodeValuesOnly: true, // 美化 URL
});

await request(`/api/restaurants?${query}`);

响应

{
  "data": [
    {
      "id": 1,
      "documentId": "cvsz61qg33rtyv1qljb1nrtg",
      "name": "GORDON RAMSAY STEAK",
      "stars": 5
    },
    {
      "id": 2,
      "documentId": "uh17h7ibw0g8thit6ivi71d8",
      "name": "GORDON RAMSAY BURGER",
      "stars": 5
    }
  ],
  "meta": {}
}
NOTE

上面的响应与默认的 REST 输出一致,不包含过滤器所遍历的关联。添加 populate 参数,例如 &populate[chef][populate][restaurants]=true,以同时返回过滤器中引用的 chef.restaurants 关联。