数据存储常见问题
API
API 调用次数有什么限制吗
使用 标准版,每天有 API 读写请求三万次的免费额度。
推送服务免费使用,并不占用免费额度,推送消息接口的调用受频率限制,具体参考:推送消息接口的限制 文档。
API 调用次数的计算
对于数据存储来说,每次 create 和 update 一个对象的数据算 1 次请求,如调用 1 次 object.saveInBackground 算 1 次 API 请求。在 API 调用失败的情况下,如果是由于应用流控超限(错误码 429)而被云端拒绝,则不会算成 1 次请求;如果是其他原因,例如权限不够(错误码 430),那么仍会算为 1 次请求。
一次请求
createsavefetchfinddeletedeleteAll
调用一次 fetch 或 find 通过 include 返回了 100 个关联对象,算 1 次 API 请求。调用一次 find 或 deleteAll 来查找或删除 500 条记录,只算 1 次 API 请求。
多次请求
saveAllfetchAll
调用一次 saveAll 或 fetchAll 来保存或获取 array 里面 100 个 对象,算 100 次 API 请求。
对于 query 则是按照请求数来计费,与结果的大小无关。query.count 算 1 次 API 请求。collection fetch 也是按照请求次数来计费。
如何获取 API 的访问日志
开发者中心后台暂不支持查看 API 访问日志。
其他语言调用 REST API 如何对参数进行编码
REST API 文档使用 curl 作为示范,其中 --data-urlencode 表示要对参数进行 URL encode 编码。
如果是 GET 请求,直接将经过 URL encode 的参数通过 & 连接起来,放到 URL 的问号后。如 https://API_BASE_URL/1.1/login?username=xxxx&password=xxxxx。
查询
如何实现大小写不敏感的查询
目前不提供直接支持,可采用正则表达式查询的办法,具体参考 StackOverflow - MongoDB: Is it possible to make a case-insensitive query。
使用各平台 SDK 的 AVQuery 对象提供的 matchesRegex 方法(Android SDK 用 whereMatches 方法)。
查询最多能返回多少结果?
- 查询最多返回 1000 条数据。
- 返回的查询结果不止一个时,总大小不超过 6 MB(为了兼容旧客户端,超过 6 MB 时不会报错,会返回截断的结果);返回一个查询结果时,大小不超过 16 MB。
查询结果最多只能返回 1000 条数据,当我需要的数据量超过了 1000 该怎么办?
可以通过每次变更查询条件,来继续从上一次的断点获取新的结果,譬如:
- 第一次查询,createdAt 时间在 2015-12-01 00:00:00 之后的 1000 条数据(最后一条的 createdAt 值是 x);
- 第二次查询,createdAt 在 x 之后的 1000 条数据(最后一条的 createdAt 是 y);
- 第三次查询,createdAt 在 y 之后的 1000 条数据(最后一条是 z);
以此类推。
可以通过 指定 objectId 范围来实现分页吗?
当前数据存储服务自动生成 objectId 的算法是基于时间的,因此确实可以通过指定 objectId 范围来实现分页。
但是,从代码可读性及严谨性出发(比如导入数据时可以指定不同格式的 objectId),推荐通过指定 createdAt 范围来实现分页。
当数据量越来越大时,怎么加快查询速度?
与使用传统的数据库一样,查询优化主要靠索引实现。索引就像字典里的目录,能帮助你在海量的文字中更快速地查词。
原则:数据量少时,不建索引。多的时候请记住,建立索引后,写入时还需要更新索引,以此来换取更少的查询时间。所以,一般来说,写少读多就多建索引,写多读少就少建索引。
索引可以在 开发者中心 > 你的游戏 > 游戏服务 > 云服务 > 数据存储 中选择对应 Class 后进入「性能与索引」自助创建。
LeanCloud 查询支持 Sum、Group By、Distinct 这种函数吗?
不支持。Group By 查询往往涉及大量对象的遍历,数据存储并 不适用这样的场景。
为此我们推荐使用「数据仓库」功能,它支持大量和高效的数据遍历,为数据分析这一场景量身定制。
默认值的查询结果为什么不对
这是默认值的限制。MongoDB 本身是不支持默认值,我们提供的默认值只是应用层面的增强,老数据如不存在相应的 key,设置默认值后并不会订正数据,只是在查询后做了展现层的优化。相应地,变更默认值后,这些 key 也会显示为新的默认值。有两种解决方案:
- 对老的数据做一次更新,查询出 key 不存在(whereDoesNotExist)的记录,再更新回去。
- 查询条件加上 or 查询,or key 不存在(whereDoesNotExist)。
如何查询非空值?
空值的具体语义取决于字段的类型和项目的实际情况。以字符串字段为例,空值可能意味着:
- 该字段不存在
- 该字段为
null - 该字段为空字符串
""
相应地,查询该字段非空的条件为 where={"some_field": {"$exists": true, "$nin": ["", null]}}。
在项目的数据模型设计阶段确定严谨的规范,有助于简化查询条件,避免因为不小心遗漏情况而出错。
例如,如果在设计上确保字符串字段为空时干脆不设置字段(不存在 ),永不将其设为 "" 和 null(强烈不推荐将字段设为 null,SDK 未提供将字段设为 null 的方法),那么只需查询 {"$exists": true} 即可。
地理位置查询错误
如果错误信息类似于 can't find any special indices: 2d (needs index), 2dsphere (needs index), for 字段名,就代表用于查询的字段没有建立 2D 索引,可以在 Class 管理的 其他 菜单里找到 索引 管理,点击进入,找到字段名称,选择并创建「2dsphere」索引类型。

如何提升标志位的查询效率?
当数据表中有很多布尔类型的数据时,可以考虑使用二进制存储提高查询效率。例如需要存储是否开启推送、是否静音、是否为会员等多个状态,可以这样表示:
111:开启推送、静音、是会员
101:开启推送、未静音、是会员
在 LeanCloud 存储为整型字段,操作这个字段的方法可以参考位运算的接口文档:REST API - 位运算。