AV.Object.extend
产生的对象需要作为全局变量保存,因为每调用 一次,就会产生一个新的类的实例,并且和之前创建的实例形成一个链表。 如果你的应用时不时出现 Maximum call stack size exceeded
错误,请 确认是否误用了该方法。objectId
是服务器端自动生成的唯一 id(非简单的自增逻辑生成),所以 objectId
是不可修改的。如果你有自定义 id 的需求,可以自己建立一个字段,逻辑上作为你的自定义 id。increment(key, amount)
方法,你可以自行定义增减的幅度(amount 缺省值为 1)。fetchWhenSave
为了帮你存储数组类数据,LeanCloud 提供了三种操作让你可以原子地改动一个数组的值(当然,他们都需要一个给定的 key):
- add: 在一个数组的末尾加入一个给定的对象
- addUnique: 只会把原本不存在的对象加入数组,所以加入的位置没有保证
- remove: 在一个数组中删除所有指定的实例
post.addUnique("tags", "Frontend");
post.addUnique("tags", "JavaScript");
你可以使用 unset
方法来删除一个实例中的单个属性:
// 这样可以删掉 pubTimestamp 属性,本来也不必要,我们完全可以用 createdAt 属性代替它。
post.unset("pubTimestamp");
// 写回 LeanCloud
post.save();
批量删除一批对象可以这样:
AV.Object.destroyAll(objects);
如果是现有对象想要关联到新对象,你同样可以通过只用它们的 objectId 来连接彼此。 请注意,不能直接像上面的例子那样将现有对象设置进去,而是必须 new
一个新对象并只设置 objectId
属性:
var post = AV.Object.createWithoutData("Post","5590cdfde4b00f7adb5860c8"); myComment.set("post", post);
或者:
var post =newPost(); post.id ='5590cdfde4b00f7adb5860c8'; myComment.set("post", post);
默认情况下,当获取一个对象时,关联的 AV.Object 不会被获取到,这些对象的值不能访问,除非像下面这样获取它们:
var post = fetchedComment.get("post");
post.fetch({
success: function(post) {
var content = post.get("content");
}
});
你可以在接下来关于 AV.Query
的章节中看到更详细的内容。一个 AV.Relation
的行为很像一个 AV.Object
数组,所以任何在数组可做的查询操作,也都可以作用在 AV.Relation
上。
如果你知道 post,想反向查询 user,可以通过 AV.Relation.reverseQuery
方法:
var query = AV.Relation.reverseQuery('_User', 'likes', post);
query.find({
success:function(users) {
// users 是表示喜欢这个 post 的用户列表。
}
});
AV.File
对象来存储,具体使用方法可见 AV.File 指南部分。关于处理数据的更多信息,可查看开发指南的数据安全部分。通过 AV.User._logInWith(platform, options)
来将微博、微信等第三方平台号绑定到 AV.User 上,例如:
AV.User._logInWith("weibo", {
"authData": {
"uid": "123456789",
"access_token": "2.00vs3XtCI5FevCff4981adb5jj1lXE",
"expiration_in": "36000"
},
success: function(user){
//返回绑定后的用户
console.dir(user);
},
error: function(err){
console.dir(err);
}
})
AV.ACL(user) 生成一个 AV.ACL 来限定 user 的访问。一个对象的 ACL 会在对象 保存的时候被存储起来,就像其他的属性一样。这样,为了创建一个当前 user 私有 的一个 note:
// 该语句应该只声明一次varNote= AV.Object.extend("Note");var privateNote =newNote(); privateNote.set("content","This note is private!"); privateNote.setACL(new AV.ACL(AV.User.current())); privateNote.save();
这个 note 只能由当前的用户所访问,但是对用户登录的设备没有限制,只要 是相同的用户就可以了。这项功能对于你如果想让用户再任何其他的设备上保存 和访问数据十分有用,比如说一个私人的 todo list 应用。
权限也能在使用者的基础上授予,你可以通过 setReadAccess 和 setWriteAccess 方 法独立的向 AV.ACL 中添加权限。比如,假设你有一条消息想要发送给一个组里 的多个用户,他们中的每一个都有读和写的权限:
// 该语句应该只声明一次varMessage= AV.Object.extend("Message");var groupMessage =newMessage();var groupACL =new AV.ACL();// userList is an array with the users we are sending this message to.for(var i =0; i < userList.length; i++){ groupACL.setReadAccess(userList[i],true); groupACL.setWriteAccess(userList[i],true);} groupMessage.setACL(groupACL); groupMessage.save();
你同样可以对所有的用户授权,只要使用 setPublicReadAccess 和 setPublicWriteAccess 就可以了。这样允许了在一个消息板上发评论的模式,比如我 们要创建一个 post 只能被它的作者修改,但是可以被所有人读取:
var publicPost = new Post();
var postACL = new AV.ACL(AV.User.current());
postACL.setPublicReadAccess(true);
publicPost.setACL(postACL);
publicPost.save();
角色继承
就像上面所描述的一样,一个角色可能包含其他的角色,表示两个角色之间的父- 子关系,这样做的结果就是任何被授予一个角色的权限都会被隐式地授予这个角 色的所有子角色.
这样的关系很经常会在有用户管理内容的程序之中看到,比如论坛,有一个很少量 的用户称为管理员,有最高的权限,比如程序设定,创建新的论坛,设定所有人能看 到的内容等等.另一类有一部分类似于”版主”的用户,这些人有责任保持用户创建 的内容是合适的.任何一个”版主”有的权限”管理员”都应该有.为了启用这种关系,你 应该使”管理员”成为”版主”的一个子角色.
var administrators = /* Your "Administrators" role */;
var moderators = /* Your "Moderators" role */;
moderators.getRoles().add(administrators);
moderators.save();
组合查询
如果你想要查找满足一系列查询的对象,你可以使用 AV.Query.or
方法来构建 查询,这样得到的结果是所有查询的并集。例如,你想查询出企业官方账号和个人账号的微博,可以这样:
var officialPosts =new AV.Query("Post"); officialPosts.greaterThan("pubUserCertificate",2);var individualPosts =new AV.Query("Post"); individualPosts.lessThan("pubUserCertificate",2);var mainQuery = AV.Query.or(officialPosts, individualPosts); mainQuery.find({ success:function(results){// results 包含企业官方账号和个人账号发布的一些微博.}, error:function(error){// 失败了.}});
你也可以对 AV.Query 加入更多的条件,如同 AND 查询一样,这样得到所有查询结果的交集。
count
操作会被时间限制所约束,它们可能会一直 返回超时错误,或者只是返回一个近似正确的值。这样的话你应该更合理地规划你 程序的结构来避免这种情况。对字符串类型做查询
使用 startWith
来限制属性值以一个特定的字符串开头,这和 MySQL 的 LIKE 操作 符很像,因为有索引所以对于大的数据集这个操作也是很高效的。
// 找出名字以 "LeanCloud" 开头的账户的微博帖子
var query = new AV.Query(Post);
query.startsWith("pubUser", "LeanCloud");
对数组值做查询
对于属性值是数组的情况,你可以这样查询数组的值中有 2 的实例列表:
query.equalTo("arrayKey",2);
你同样可以用下面的方式找到属性值中同时包含元素 2,3,4 的实例列表:
query.containsAll("arrayKey",[2,3,4]);
此外,你还可以根据数组长度来查询,比如查询 arrayKey
的长度为 3 的对象列表:
query.sizeEqualTo('arrayKey', 3);
剩下的字段可以之后用返回的对象的 fetch
方法来获取:
query.first().then(function(result) {
// 这里只会返回指定的属性,再次获取全部属性.
return result.fetch();
}).then(function(result) {
// 这里会返回所有属性.
});
如果想让返回的对象的某个属性匹配多个值,你可以使用 containedIn
,提供一个数组就可以了。这样通常可以用单个的查询来获取多个结果,比如 你要查询 「LeanCloud官方客服」,「LeanCloud江宏」,「滚滚艾买提」 三个账号的微博时,可以使用 containedIn
(类似 SQL 中的 in 查询)方法来实现:
query.containedIn("pubUser",
["LeanCloud官方客服", "LeanCloud江宏", "滚滚艾买提"]);
notContainedIn
方法来查询在集合之外的目标对象。你可以使用 matchesKeyInQuery
方法来进行嵌套的子查询。例如,在微博这类应用中有三类数据:一个类是微博帖子信息(Post),另一个类是用户账户信息(AVUser),还有一个类是用户之间互相关注的信息(UserFollow),要找出当前用户关注的人发布的微博,则:
// 该语句应该只声明一次varUserFollow= AV.Object.extend("UserFollow");varPost= AV.Object.extend("Post");// 先找到当前登录用户关注的用户列表var userQuery =new AV.Query(UserFollow); userQuery.equalTo("follower", AV.User.current());// 找到这些被关注者发布的微博var postQuery =new AV.Query(Post); postQuery.matchesKeyInQuery("author","followee", userQuery); postQuery.find({ success:function(results){// 得到当前用户关注的人发布的微博}});
相反,要从一个查询中获取一组对象,该对象的一个键值,与另一个对象的键值并不匹配,可以使用 doesNotMatchKeyInQuery
。 例如,找出当前用户没有关注的人发布的微博:
var postQuery = new AV.Query(Post);
postQuery.doesNotMatchKeyInQuery("author", "followee", userQuery);
postQuery.find({
success: function(results) {
// 得到非当前用户关注的人发布的微博
}
});
如果你想要查询含有某一特定属性的对象,你可以使用 exists
。相对地,如果你想获 取没有这一特定属性的对象,你可以使用 doesNotExist
:
// 查找含有 pubTimestamp 属性的微博
query.exists("pubTimestamp");
// 查找不含有 pubTimestamp 属性的微博
query.doesNotExist("pubTimestamp");