加入leancloud是什么需要具备什么样的能力

[京/昆山] LeanCloud 开放诸多职位!Lean on LeanCloud! - CNode技术社区
这家伙很懒,什么个性签名都没有留下。
为移动应用开发者提供一流的工具、平台和服务,力求为复杂的问题提供优雅的答案。
很多人说云计算的到来给了每个人几乎无限的计算资源和存储资源。然而在现实中还并不是这样的。对于大多数云服务,计算资源还是以「台」为单位的虚拟机,设计和实现易于扩展的后端架构仍然是用户的责任,使用一台虚拟机和使用一百台虚拟机的运维负担显然是不一样的。LeanCloud提供了按请求数、链接数这样被实际有效使用的资源付费的模式,并把用户从后端的设计、开发、运维中解放出来,真正聚焦于产品。每一天都有数千活跃开发者在使用 LeanCloud 进行开发,如果每位开发者能因此而节约一小时,LeanCloud 每天就为用户节约了数百个工作日的成本。
无论具体职位是什么我们对每位成员都有一些共同的期望:
我们有开放透明的文化,希望每个成员能共同维护,不让这样的文化因为人数的增加而稀释。
我们是一家注重细节的公司。我们知道如果犯一个很小的错误也可能给用户造成损失,所以「抓大放小」不是我们的哲学,只要是错了的,无论是程序的 bug 还是一个错字,我们都会重视并改正。
我们希望每个团队成员都既可以独当一面,也可以全面参与各方面的工作。工程师也要懂产品、懂用户、能沟通、能布道。
我们努力给每个人公平的回报,除了让薪酬和期权公开和透明外,也请律师为大家解答不熟悉的期权问题。同时我们也很注意为每位同事的成长提供好的条件,我们曾请咨询师为每个人做一对一的培训评估,免费报销书籍,以及免费提供各类线上学习的帐号。
我们希望新成员因为认同我们的事业和文化而加入,所以我们不会像其他公司一样把美女放在招聘贴里,当然也不会贴出我们不久前去大理 offsite 和去京城最好的法餐厅聚餐的照片,人体工学座椅、免费上门推拿、胶囊咖啡机、零食、午餐之类就更不值得在这里说了。
持续热招职位:
iOS 工程师:开发基于 LeanCloud 的面向开发者的移动应用
精通 Objective-C 语言和 iPhone 平台开发技术,包括 UI、网络等
熟练掌握 Xcode 开发工具和相关开发测试工具
熟悉 TCP/IP、HTTP 等网络协议
有 LeanCloud、Parse 或相关 mBaaS 产品开发经验者优先
有 App Store 或 Mac App Store 上架项目或者有个人的成熟作品者优先
是 team player,有优秀的学习、沟通、协作能力。
Android 工程师:开发基于 LeanCloud 的面向开发者的移动应用
技术基础扎实,熟悉常用数据结构与算法
精通 Java 语言和 Android API
熟悉 TCP/IP、HTTP 等网络协议
两年以上 Android 平台开发经验
有 LeanCloud、Parse 或相关 mBaaS 产品开发经验者优先
是 team player,有优秀的学习、沟通、协作能力。
Web 全栈工程师:开发基于 LeanCloud 的 Web 应用,包括 LeanCloud 的工单系统及各种周边工具
精通JavaScript, CSS, 及HTML;
精通至少一种JS框架(如jQuery,Backbone,Angular等);
熟悉Linux 或 Mac 开发环境并能熟练使用常用命令行工具和开发工具;
技术基础扎实,熟悉常用数据结构与算法;
是 team player,有优秀的学习、沟通、协作能力;
有设计能力者优先
MongoDB 专家:负责优化 MongoDB 集群的性能及可靠性
熟悉 MongoDB 源码,为官方 repository 提交过 patch 的优先;
精通分布式系统知识;
熟悉 Linux 进程及 IO 系统;
是 team player,有优秀的学习、沟通、协作能力。
Docker 专家:负责开发 docker 集群的管理和监控系统
熟悉 Docker 源码,为官方 repository 提交过 patch 的优先;
精通系统资源虚拟化相关知识;
熟悉 Linux 进程及 IO 系统;
是 team player,有优秀的学习、沟通、协作能力。
技术支持专家:为 LeanCloud 客户提供资讯及技术支持,与工程师一起改进技术支持系统,协助改进文档,为研发团队提供有效的用户反馈。
有良好的程序设计功底及经验;
有移动应用开发经验者优先;
有优秀的口头及书面沟通能力;
性格和善、能与不同类型的人耐心交流;
是 team player,有优秀的学习、沟通、协作能力。
Lead Designer:主导公司在设计方面的工作,建立一致的语言和风格,让设计贯穿在产品执行的各个环节和公司日常工作的方方面面。
有丰富的用户体验及界面设计经验;
有面向开发者的产品设计经验者优先;
有良好的沟通能力,能带领设计团队完成产品各个阶段的设计工作;
有能力定义符合公司品牌形象的设计语言及设计规范。
学了新词 mBaas - Mobile Back End As A Service
你们的东西部署太慢了,而且还经常报错。最近有些不稳定
CNode 社区为国内最专业的 Node.js 开源技术社区,致力于 Node.js 的技术研究。
服务器赞助商为
,存储赞助商为
,由提供应用性能服务。
新手搭建 Node.js 服务器,推荐使用无需备案的主题 : 有没有用leancloud的?价格方案变了
级别: 新手上路
可可豆: 68 CB
威望: 68 点
在线时间: 153(时)
发自: Web Page
来源于&&分类
有没有用leancloud的?价格方案变了&&&
新年第一天收到邮件,然后登陆一看leancloud改价格了。我业余时间做了个app,维护了两年了,主要是提供资料给用户下载的,用户不多。这个app每个月的下载流量大概在100多个G,按照原有的价格方案,每个月差不多30元。然而,按照新的价格方案,如果是完全免费的开发版,每个月只能用15G的流量;如果用商用版,每个月保底消费900元!最近还在自学微信小程序开发,打算把app做个小程序版。哎,新年第一天... 大家都用什么baas,求推荐...________________________更新,已证实价格方案改变的地方和小开发者没什么关系,只是官方写的太容易让人误解了,稍候leancloud会更新价格。[ 此帖被liemlian在 01:40重新编辑 ]
级别: 侠客
可可豆: 308 CB
威望: 162 点
在线时间: 964(时)
发自: Web Page
bmob,可是感觉动不动就崩,-_-,leancloud会这样吗?
级别: 新手上路
可可豆: 92 CB
威望: 92 点
在线时间: 434(时)
发自: Web Page
用的leancloud,也了解过bmob,bmob用起来应该会比leancloud便宜不少吧。leancloud总体还算稳定,偶尔出问题。leancloud基本费不算贵吧,按商用的话,一个月也就900.主要是api调用计费太贵了,现在还涨价了。用户量稍微大点的就很难抗住。不过用起来确实很方便。
级别: 新手上路
可可豆: 8 CB
威望: 8 点
在线时间: 64(时)
发自: Web Page
搞个服务器不是更方便
级别: 圣骑士
可可豆: 6109 CB
威望: 6109 点
在线时间: 2578(时)
发自: Web Page
已删除.......................[ 此帖被bzsonic123在 13:23重新编辑 ]
级别: 骑士
可可豆: 778 CB
威望: 768 点
在线时间: 593(时)
发自: Web Page
回 4楼(bzsonic123) 的帖子
不会吧,900美金。。。
级别: 圣骑士
可可豆: 6109 CB
威望: 6109 点
在线时间: 2578(时)
发自: Web Page
回 5楼(oldinzaghi) 的帖子
官方已澄清,美国节点是标错价了,不过900人民币我依旧觉得太贵了,正在考虑其它方案[ 此帖被bzsonic123在 13:21重新编辑 ]
图片:屏幕快照
下午7.23.39.png
级别: 骑士
可可豆: 778 CB
威望: 768 点
在线时间: 593(时)
发自: Web Page
回 6楼(bzsonic123) 的帖子
我已经问过leancloud了,是标错了,价格也是30元人民币一天详情看这个帖子:
级别: 新手上路
可可豆: 45 CB
威望: 45 点
在线时间: 82(时)
发自: Web Page
貌似,都在收割用户了,最好还是自己搞吧
关注本帖(如果有新回复会站内信通知您)
苹果公司现任CEO是谁?2字 正确答案:库克
发帖、回帖都会得到可观的积分奖励。
按"Ctrl+Enter"直接提交
关注CocoaChina
关注微信 每日推荐
扫一扫 浏览移动版LeanCloud江宏:坦诚与认真——创业者不可忽略的素质编者注:本文根据 Lean Cloud CEO 江宏在上的演讲整理而成。1.产品数据的吹嘘很容易鉴别
产品数据,我们经常看到一些新闻,可能没怎么听说过的产品,上来就说自己有几千万甚至上亿用户,其实这是很少鉴别的,你只要想一想自己认识的人当中有几个是他的用户,再想一想中国有多少互联网用户,其实很容易得出结论。2.不诚实会付出更大的代价无论是融资,或者招聘,或者做产品,任何复杂的事情,往往都会分为几个阶段。在每个阶段,产出的价值一定是大于上个阶段产出的价值的,因为你投入了更多资源,如果价值反而变小了,就没必要去做这一步了。 这也就意味着,你在下个阶段发现问题,一定比上个阶段发现问题所带来的代价要大,浪费的资源更多。而不诚实带来的问题在于,比较容易的让你通过前面的阶段。事实毕竟是事实,问题会暴露出来,到那个时候会让你付出更大的代价。3.虚报数字对创业者和公司都有损害
拿融资来说,在开始接触的阶段,双方就能坦诚相待、发现问题,其实对创业者和投资人来说,都是代价最低的。如果一开始虚报数字,到了尽职调查的阶段才发现问题,那时候双方已经投入了很多时间和精力,这个机会成本是非常大的。就算在这个阶段蒙混过关,融资之后如果投资人发现公司的发展跟预期非常不一样,被迫去行使一些保护性条款来止损,往往会对这个公司造成致命的伤害。现在的VC大部分都是有钱任性,现在不流行说人傻钱多了,不会管那么多。但其实,一个创业者如果拿了VC的钱,在一件不会成功的事情上努力很多年,其实对自己和团队都是一种极大的浪费。所以从这个角度看,一个本来不应该拿到投资的项目,侥幸拿到了投资,不一定是好事,或者说一定不是一件好事。招聘也是一样,最好是双方都在比较早的阶段发现相互不匹配,各自做其他选择。最不好的就是入职一段时间再离职,这时候工作上的问题已经造成,而双方都已经投入了很宝贵的时间。4.公开薪酬营造坦诚的氛围在 LeanCloud,我们从一开始就希望能够营造一种坦诚的氛围,我们公开了我们计算薪酬的方式,这个公式里面每一类职位都有一个薪酬的基数,这些基数和系数都在公开的文档里面。所以,对内每个员工,他都知道自己的月薪是怎么计算出来的,对外我们每发出一个 Offer 会附上一个链接,然后告诉这个候选人。根据面试,我们把他的能力水平定在哪个级别,所以他的月薪应该是多少,我们不会去问他他以前拿多少钱,或者期望值是多少,所以也就没有谈判。5.站在风口踏踏实实地做事现在在互联网圈可能被引用最多的一句话,就是雷军说的站在风口猪都可以飞起来,这句话好象今天前面已经出现了两次,现在各种风刮的那么猛烈,北京创业氛围天空应该是这样子的,而雾霾的时候却是这样子的。现在确实有很好的创业机会,这点是没错的,但天下的聪明人很多,所以对每个机会都不会只有一个人看到,所以站在风口并取代不了踏踏实实做事情。我觉得,有很多人他们过度的关注了雷军顺势而为的成功,但没有关注到这背后的辛苦和认真。6.公司和产品一样有自己的品牌和风格对一个公司来说,在不同阶段可能会有多个产品,而同一个产品也可能面临多次转型。商业上的成功往往依赖于很多因素,而其中有很多并不是主观可控的。所以我认为,对一个创业者来说,他最重要的产品其实是他的公司,因为这家公司的文化、口碑,员工是不是喜欢这家公司,竞争对手和合作伙伴如何评价这家公司,往往是创始人可以几乎完全把握的。所以,经营一家公司,也要像做一个产品一样,要有自己的风格和品牌,要追求有所创新,也要敢于打破现状。每位创业者,都应该努力做一家好公司。分享下载极客公园客户端iOS下载LeanCloud iOS 数据模型设计简介_IOS_第七城市
LeanCloud iOS 数据模型设计简介
LeanCloud 算是自己第一个接触的真实数据结构应用,本篇主要是用来总结看官方文档过程中习得的一些关于 LeanCloud 数据存储&获取的收获。本篇是基于个人阅读过程中的理解总结的文章,也可直接查看 LeanCloud 官方文档。如有不对的地方,欢迎拍砖~LeanCloud 存储后台大量采用了 MongoDB 这种文档数据库来存储结构化数据,得以为我们提供了面向对象的、海量的、schema free 的存储能力。Schema 是什么?Schema 是对一个数据库的结构描述。在一个关系型数据库里面,Schema 定义了表、每个表的字段,还有表跟字段之间的关系。查看资料后个人的理解是,Schema 就像一个 namespace ,不同的 Schema 下的数据不会互相影响,除非有引用的权限。点到为止,后面再做深入了解。数据库常识先对比下关系型数据库、MangoDB 和 LeanCloud 的对应属于,如下表:RDBMSMongoDBLeanCloud DatabaseDatabaseApplicationTableCollectionClassRowDocumentObjectIndexIndexIndexJOINEmbedded, ReferenceEmbedded Object, Pointer, Relation自己主要做的是 iOS 平台的开发,从上面的对比中可以很友好的发现,LeanCloud 支持了对象式的存储,看到的第一眼感觉还是比较亲切的~关系型数据库( RDBMS )和文档型数据库的区别在于:RDBMS 优化了数据存储效率文档数据库 优化了数据访问传统的关系型数据模型,所有的数据都会被映射到二维的表结构行与列中;LeanCloud 提供了动态的对象模型(MongoDB 的文档模型),还可以很方便的内嵌子对象和数组。表型数据结构与动态的文档型数据结构在企业级的复杂数据结构中,使用 JSON 对象来建模比表更为轻便和高效。通过内嵌子对象和数组,JSON 对象可以和应用层的数据结构对齐。可以更容易得将应用层的数据映射到数据库里的对象。对于表来说,将应用层的数据映射到关系数据库的表中,需要额外的对象关系映射层(ORM),这样就降低了 Schema 拓展和查询的灵活性,更为复杂。下面以一个例子来说明 RSBMS 表结构与 LeanCloud 文档结构的差异:(下图的数据显示的是每个车主拥有每辆车的信息)PERSONPer_IDSurnameFirst_NameCity0ZhouYueLondon1JonyFangLondon2LoTomasiZurichCARCar_IDModelYearValuePers_ID101LAND ROVER20223000000102LAND ROVER20225000001103Porsche202613180001103BYD20131000000由上表可以看出,RDBMS 通过 Pers_ID 域来链接 PERSON 表和 CAR 表。文档模型,通过内嵌子对象和数组将相关的数据提前合并到一个单一的数据结构中,传统形势的跨表的行与列都被存储到了一个文档内,更为方便。再使用 LeanCloud 对上面表结构数据进行数据建模。需要创建这样的 Schema:一个单一的 Person 对象,对象内通过一子对象数组来保存该用户所拥有的每一个 Car,如下:{first_name: "Jony",surname: "Fang",city: "London",cars: [
{model: "LAND ROVER", year: 2022, value: 500000},
{model: "Persche", year: 2026, value: 1318000}
]}文档数据库里的一篇文档,相当于 LeanCloud 平台的一个对象。再以一个博客平台的例子来展示关系模型和文档模型的区别。依赖 RDBMS 的应用需要 join 5 张不同的表来获得一篇博客的完整数据;而在 LeanCloud 中,所有的博客数据都包含在一个文档中,博客作者和评论者的用户信息通过一个到 User 的引用(指针)进行关联。文档模型的其它优点除了数据表现更加自然外,文档模型还由性能和拓展性的优势:通过单一调用即可获得完整的文档数据,避免了多表 join 的开销。LeanCloud 的 Object 物理上作为一个单一的块进行存储,只需要一次内存或者磁盘的读操作即可。RDBMS 则相反,一个 join 操作需要从不同的地方多次读取操作才可以完成。文档是自包含的,将数据库内容分布到多个节点(sharding)会更为简单,同时也更容易通过普通硬件的水平扩展获得更高性能。嗯~上面算是一个纪录,后面再深入细致了解文档模型的存储及性能。设计文档 Schema应用的数据访问模式决定了 Schema 设计,因此我们需要明确几点:数据库读写操作的比例以及是否需要重点优化某一方的性能对数据库进行查询和更新的操作类型数据生命周期和文档的增长率对于普通的 [key--value] 对来说,和 RDBMS 的表结构差别不大。对于 1:1 或 1:many 的关系可以使用内嵌对象的方式。哪些类型使用内嵌方式会更好呢?数据间有“所有”和“包含”的关系经常需要同时、原子改动的属性作为一个对象嵌入到一个单独属性(key)中举一个例子,建立一个数据结构,纪录每个学生的家庭住址信息(可以把地址信息作为一个整体嵌入到 Student 类中)。
AVObject *studentTom = [[AVObject alloc] initWithClassName:@"Student"];
[studentTom setObject:@"Tom" forKey:@"name"];
NSDictionary *addr = @{
@"city" : "ShangHai",
@"address" : "BaoShan",
@"postcode" : "10000"
[studentTom setObject:addr forKey:@"address"];
[studentTom saveInBackground];// 保存到 LeanCloud 云端然而并不是所有的 1:1 关系都适合内嵌的方式,下面这些场景使用引用会更为合适:一个对象呗频繁地读取,但部分子对象却很少会被访问对象的一部分属性频繁被更新,数据大小持续增长,但部分子对象属性基本保持稳定不变对象大小超过了 LeanCloud 最大 16 MB 限制接着再总结下在 LeanCloud 上如何通过“引用”机制来实现复杂的数据模型。复杂关系模型的设计数据对象之间存在 3 种类型的关系。一对一关系、一对多关系、多对多关系。LeanCloud 支持4种方式来构建对象之间的关系(通过 MongoDB 的文档引用来实现):Pointers(一对一、一对多)Arrays(一对多、多对多)AVRelation(多对多)关联表(多对多)一对多关系创建一个一对多关系时,我们需要根据关系中包含的对象数量,来选择使用 Pointers 还是 Arrays 来实现。如果关系“多”方包含的对象数量很多(&100左右),必须使用 Pointers。如果对象数量很小(&100),使用 Arrays 会更方便,特别是获取父对象的同时获取所有相关的对象(“多”方)。使用 Pointers 实现一对多关系Pointers 存储中国的“省份”与“城市”就是一对多关系,以“广东省”下的“深圳市”、“广州市”为例,使用 Pointers 来存储。
AVObject *GuangZhou = [[AVObject alloc] initWithClassName:@"City"];
[GuangZhou setObject:@"广州市" forKey:@"name"];
AVObject *GuangDong = [[AVObject alloc] initWithClassName:@"Province"];
[GuangDong setObject:@"广东省" forKey:@"name"];
[GuangZhou setObject:GuangDong forKey:@"dependent"];// 为广州市设置 dependent 属性为广东省
[GuangZhou saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (succeeded) {
// 广州市被保存成功
// 广东省无需被单独保存,因为在保存广州市的时候已经上传到云端。保存关联对象的同时,被关联的对象也会随之被保存到云端。接着,我们需要关联一个已经在云端的对象,例如将“东莞市”添加至“广东省”,方法如下:
// 假设 GuangDong 的 objectId 为 b09f857a603632
AVObject *GuangDong = [AVObject objectWithClassName:@"Province" objectId:@"b09f857a603632"];
AVObject *DongGuan = [[AVObject alloc] initWithClassName:@"City"];
[DongGuan setObject:@"东莞市" forKey:@"name"];
[DongGuan setObject:GuangDong forKey:@"dependent"];// 为东莞市设置 dependent 属性为广东省
[DongGuan saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (succeeded) {
// 东莞市被保存成功
}];执行上述代码上传成功后,在应用控制台可以看到 dependent 字段显示为 Pointer 数据类型,而它本质上存储的是一个指向 Province 这张表的某个 AVObject 的指针。Pointer 查询如果已知一个城市,想知道他的省份,如下操作:
// 假设东莞市作为 City 对象存储的时候它的 objectId 是 568e743c00b09aa22162b11f
AVObject *DongGuan = [AVObject objectWithClassName:@"City" objectId:@"568e743c00b09aa22162b11f"];
NSArray *keys = @[@"dependent"]; // 指定要获取的 objects
[DongGuan fetchInBackgroundWithKeys:keys block:^(AVObject *object, NSError *error) {
// 获取广东省
AVObject *province = [object objectForKey:@"dependent"];
}];如果查询结果中包含了 City,并想通过一次查询同时把对应的 Province 一并加载到本地,如下操作:
AVQuery *query = [AVQuery queryWithClassName:@"City"];
// 查询名字是广州市的城市
[query whereKey:@"name" equalTo:@"广州市"];
// 找出城市对应的省份
[query includeKey:@"dependent"];
[query findObjectsInBackgroundWithBlock:^(NSArray *cities, NSError *error) {
// cities 的结果为 name 等于广州市的集合,当然我们知道现实中只存在一个广州市
for (AVObject *city in cities) {
// 获取对应的省份,并不需要网络访问
AVObject *province = [city objectForKey:@"dependent"];
}];如果已知一个省份,要找出它的所有下辖城市,操作如下:
// 假设 GuangDong 的 objectId 为 b09f857a603632
AVObject *GuangDong = [AVObject objectWithoutDataWithClassName:@"Province" objectId:@"b09f857a603632"];
AVQuery *query = [AVQuery queryWithClassName:@"City"];
[query whereKey:@"dependent" equalTo:GuangDong];
[query findObjectsInBackgroundWithBlock:^(NSArray *cities, NSError *error) {
for (AVObject *city in cities) {
// cities 的结果为广东省下辖的所有城市
}];如上几步操作,就已经使用 Pointers 实现了一个简单的一对多(省份-城市)关系数据的存储和获取。使用 Arrays 实现一对多关系Arrays 存储当一对多关系中所包含的对象数量很少时,使用 Arrays 比较理想。Arrays 可以通过 includeKey 进行查询。传递对应的 key 可以在获取一方对象数据的同时获取到所有多方对象的数据。但如果关系中包含的对象数量巨大,相应的查询会相应缓慢。前面说的城市与省份的对应关系也可以使用 Arrays 来实现。重新建立对象,为 Province 表添加一列 cityList 来保存城市数组,如下操作:
AVObject *GuangDong = [[AVObject alloc] initWithClassName:@"Province"];
[GuangDong setObject:@"广东省" forKey:@"name"];
AVObject *GuangZhou = [[AVObject alloc] initWithClassName:@"City"];
[GuangZhou setObject:@"广州市" forKey:@"name"];
AVObject *ShenZhen = [[AVObject alloc] initWithClassName:@"City"];
[ShenZhen setObject:@"深圳市" forKey:@"name"];
// 把广州和深圳放置在一个数组里面,然后把这个数组设置为广东的 cityList 属性
NSArray *cityList = [NSArray arrayWithObjects:GuangZhou, ShenZhen, nil];
[AVObject saveAllInBackground:cityList block:^(BOOL succeeded, NSError *error) {
[GuangDong addUniqueObjectsFromArray:@[GuangZhou, ShenZhen] forKey:@"cityList"];
// 只要保存 GuangDong 即可,它关联的对象都会一并被保存在云端。
[GuangDong saveInBackground];
}];Arrays 查询获取上面存储的 City 对象,如下操作:
// 假设 GuangDong 的 objectId 是 56abc
AVObject *GuangDong = [AVObject objectWithoutDataWithClassName:@"Province" objectId:@"56abc"];
[GuangDong fetchIfNeededWithKeys:[NSArray arrayWithObjects:@"cityList",nil]];
[GuangDong fetchIfNeededInBackgroundWithBlock:^(AVObject *object, NSError *error) {
NSArray *cityList = [GuangDong objectForKey:@"cityList"];
for (AVObject *city in cityList) {
// cityList 的结果为广东省下辖的所有城市
// 下面可以打印出所有城市的 objectId
NSLog(@"objectId: %@", city.objectId);
// 下面可以打印出所有城市的 name
NSLog(@"name: %@", [city objectForKey:@"name"]);
}];如果要在查询某一个省份的时候,顺便把所有下辖的城市也获取到本地,可以在构建查询的时候使用 includeKey 操作,这样就可以通过一次查询同时获取 cityList 列中存放的 City 对象数组,如下操作:
AVQuery *query = [AVQuery queryWithClassName:@"Province"];
[query whereKey:@"name" equalTo:@"广东省"];
[query includeKey:@"cityList"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// objects 是查询 Province 这张表的结果,因为我们是根据 name 查询的,表中 name
等于广东省的有且只有一个数据
// 因此这个集合有且只有一个数据
for (AVObject *province in objects) {
NSArray *cityList = [province objectForKey:@"cityList"];
for (AVObject *city in cityList) {
// 打印出所有城市的 objectId
NSLog(@"city objectId: %@", city.objectId);
// 打印出所有城市的 name
NSLog(@"city name: %@", [city objectForKey:@"name"]);
}];同样的,也可以通过已知的城市来查询它的上级省份,例如查找南京的所属省份:
AVObject *NanJing = [AVObject objectWithoutDataWithClassName:@"City" objectId:@"56a"];
AVQuery *query = [AVQuery queryWithClassName:@"Province"];
[query whereKey:@"cityList" equalTo:NanJing];
[query getFirstObjectInBackgroundWithBlock:^(AVObject *province, NSError *error) {
NSLog(@"province name: %@", [province objectForKey:@"name"]);
}];多对多关系以选课系统为例,为 Student 对象和 Course 对象建模。一个学生可以选多门课程,一个课程选的学生也可以有多个,这样就有了一个多对多的关系。可以使用 Arrays、Relation 或创建自己的关联表来实现这种关系。具体选择哪种方式取决于是否需要为这个关系附加属性。如果不需附加属性,Relation 或 Arrays 最为简单;如果多对多关系中任何一方对象比较多(&100左右),Relation 或关联表会更好;如果需要为关系附加一些属性,可以创建一个独立的表(关联表)来存储两端的关系,附加的属性用于描述这个关系,不适用于描述关系中的任何一方。附加的属性可以是:关系的创建时间关系的创建者某人查看此关系的次数使用 Relation 实现多对多关系Relation 的存储一个学生可以选多门课程,一个课程可以被多人选择。下面使用 Relation 来构建 Student 和 Course 之间的关系。一个学生选多门课程
AVObject *studentTom = [[AVObject alloc] initWithClassName:@"Student"];// 学生 Tom
[studentTom setObject:@"Tom" forKey:@"name"];
AVObject *courseLinearAlgebra = [[AVObject alloc] initWithClassName:@"Course"];// 线性代数
[courseLinearAlgebra setObject:@"Linear Algebra" forKey:@"name"];
AVObject *courseObjectOrientedProgramming = [[AVObject alloc] initWithClassName:@"Course"];// 面向对象程序设计
[courseObjectOrientedProgramming setObject:@"Object-Oriented Programming" forKey:@"name"];
AVObject *courseOperatingSystem = [[AVObject alloc] initWithClassName:@"Course"];// 操作系统
[courseOperatingSystem setObject:@"Operating System" forKey:@"name"];
[AVObject saveAllInBackground:@[courseLinearAlgebra,courseObjectOrientedProgramming,courseOperatingSystem] block:^(BOOL succeeded, NSError *error) {
if (error) {
// 出现错误
// 保存成功
AVRelation *relation = [studentTom relationforKey:@"coursesChosen"];// 新建一个 AVRelation,用来保存所选的课程
[relation addObject:courseLinearAlgebra];
[relation addObject:courseObjectOrientedProgramming];
[relation addObject:courseOperatingSystem];
[studentTom saveInBackground];
}];Relation 的查询获取某课程的所有选课学生,如下操作:
// 微积分课程
AVObject *courseCalculus = [AVObject objectWithClassName:@"Course" objectId:@"562da3fdddbd49"];
// 构建 Student 的查询
AVQuery *query = [AVQuery queryWithClassName:@"Student"];
// 查询条件
[query whereKey:@"coursesChosen" equalTo:courseCalculus];
// 执行查询
[query findObjectsInBackgroundWithBlock:^(NSArray *students, NSError *error) {
// students 就是所有选择了微积分的学生
for (AVObject *student in students) {
// 打印 student 的 objectId 以及 name
NSLog(@"objectId: %@", student.objectId);
NSLog(@"name: %@", [student objectForKey:@"name"]);
}];获取某学生学习的所有课程,可以通过如下查询来获取这种方向关系的结果:
// 假设 Tom 被保存到云端之后的 objectId 是 562da3fdddbd49
AVObject *studentTom = [AVObject objectWithClassName:@"Student" objectId:@"562da3fdddbd49"];
// 读取 AVRelation 对象
AVRelation *relation = [studentTom relationforKey:@"coursesChosen"];
// 获取关系查询
AVQuery *query = [relation query];
[query findObjectsInBackgroundWithBlock:^(NSArray *courses, NSError *error) {
// courses 就是当前学生 Tom 所选择的所有课程
for (AVObject *course in courses) {
// 打印 course 的 objectId 以及 name
NSLog(@"objectId: %@", course.objectId);
NSLog(@"name: %@", [course objectForKey:@"name"]);
}];使用关联表实现多对多关系有时需要为关系添加更多的附加信息,例如上面的学生选课系统,要了解学生打算选修的这门课课时是多久,或学生通过哪种平台选课(手机、网站...)。AVRelation 无法满足这些附加信息的需求,AVRelation 不支持额外的自定义属性,可以通过关联表来构建数据。如下构建一个独立的表 StudentCourseMap 来保存 Student 和 Course 关系:字段类型说明coursePointerCourse 指针实例studentPointerStudent 指针实例durationArray所选课程的开始时间和结束时间,如["",""]platformString选课平台,如 iOS下面是实现代码:
AVObject *studentTom = [[AVObject alloc] initWithClassName:@"Student"];// 学生 Tom
[studentTom setObject:@"Tom" forKey:@"name"];
AVObject *courseLinearAlgebra = [[AVObject alloc] initWithClassName:@"Course"];// 线性代数
[courseLinearAlgebra setObject:@"Linear Algebra" forKey:@"name"];
AVObject *studentCourseMapTom= [[AVObject alloc] initWithClassName:@"StudentCourseMap"];// 选课表对象
// 设置关联
[studentCourseMapTom setObject:studentTom forKey:@"student"];
[studentCourseMapTom setObject:courseLinearAlgebra forKey:@"course"];
// 设置学习周期
[studentCourseMapTom setObject: @[@"",@""] forKey:@"duration"];
// 获取操作平台
[studentCourseMapTom setObject: @"iOS" forKey:@"platform"];
// 保存选课表对象
[studentCourseMapTom saveInBackground];查询某课程所有的选修学生:
// 微积分课程
AVObject *courseCalculus = [AVObject objectWithClassName:@"Course" objectId:@"562da3fdddbd49"];
// 构建 StudentCourseMap 的查询
AVQuery *query = [AVQuery queryWithClassName:@"StudentCourseMap"];
// 查询所有选择了线性代数的学生
[query whereKey:@"course" equalTo:courseCalculus];
// 执行查询
[query findObjectsInBackgroundWithBlock:^(NSArray *studentCourseMaps, NSError *error) {
// studentCourseMaps 是所有 course 等于线性代数的选课对象
// 然后遍历过程中可以访问每一个选课对象的 student,course,duration,platform 等属性
for (AVObject *studentCourseMap in studentCourseMaps) {
AVObject *student =[studentCourseMap objectForKey:@"student"];
AVObject *course =[studentCourseMap objectForKey:@"course"];
NSArray *duration = [studentCourseMap objectForKey:@"duration"];
NSLog(@"platform: %@", [studentCourseMap objectForKey:@"platform"]);
}];查询某一个学生选修的所有课程,如下操作:
AVObject *studentTom = [AVObject objectWithoutDataWithClassName:@"Student" objectId:@"562da3fc00b0bf37b117c250"];
AVQuery *query = [AVQuery queryWithClassName:@"StudentCourseMap"];
[query whereKey:@"student" equalTo:studentTom];
[query findObjectsInBackgroundWithBlock:^(NSArray *courses, NSError *error) {
for (AVObject *course in courses) {
}];使用 Arrays 实现多对多关系使用 Arrays 实现多对多关系,关系中一方有一个数组列来包含关系另一方的一些对象。以选课系统为例,使用 Arrays 来实现学生选课的操作:
AVObject *studentTom = [[AVObject alloc] initWithClassName:@"Student"];// 学生 Tom
[studentTom setObject:@"Tom" forKey:@"name"];
AVObject *courseLinearAlgebra = [[AVObject alloc] initWithClassName:@"Course"];// 线性代数
[courseLinearAlgebra setObject:@"Linear Algebra" forKey:@"name"];
AVObject *courseObjectOrientedProgramming = [[AVObject alloc] initWithClassName:@"Course"];// 面对对象程序设计
[courseObjectOrientedProgramming setObject:@"Object-Oriented Programming" forKey:@"name"];
AVObject *courseOperatingSystem = [[AVObject alloc] initWithClassName:@"Course"];// 操作系统
[courseOperatingSystem setObject:@"Operating System" forKey:@"name"];
// 所选课程的数组
NSArray *courses = @[courseLinearAlgebra,courseObjectOrientedProgramming,courseOperatingSystem];
// 使用属性名字 coursesChosen 保存所选课程的数组
[studentTom setObject:courses forKey:@"coursesChosen"];
// 保存在云端
[studentTom saveInBackground];当查询某学生所有选的课程,使用 includeKey 操作来获取对应的数组值,操作如下:
AVQuery *query = [AVQuery queryWithClassName:@"Student"];
[query whereKey:@"name" equalTo:@"Tom"];
// 以下这条语句是关键语句
[query includeKey:@"coursesChosen"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// objects 是查询 Student 这张表的结果,因为我们是根据 name 查询的,我们假设表中 name
等于 Tom 的学生有且只有一个数据
// 因此这个集合有且只有一个数据
for (AVObject *tom in objects) {
NSArray *coursesChosenArray = [tom objectForKey:@"coursesChosen"];
for (AVObject *course in coursesChosenArray) {
// coursesChosenArray 的结果为 Tom 选修的所有课程
// 下面可以打印出所有课程的 objectId
NSLog(@"objectId: %@", course.objectId);
// 下面可以打印出所有课程的 name
NSLog(@"name: %@", [course objectForKey:@"name"]);
}];当查询某课程所有选修的学生时,如下操作:
// 假设线性代数的 objectId 是 562da3fd60b2c1e233c9b250
AVObject *courseLinearAlgebra = [AVObject objectWithoutDataWithClassName:@"Course" objectId:@"562da3fd60b2c1e233c9b250"];
// 构建针对 Student 这张表的查询
AVQuery *query = [AVQuery queryWithClassName:@"Student"];
[query whereKey:@"coursesChosen" equalTo:courseLinearAlgebra];
[query findObjectsInBackgroundWithBlock:^(NSArray *students, NSError *error) {
// students 即为所有选择了线性代数这门课的学生
for (AVObject *student in students) {
// 下面可以打印出所有学生的 objectId、name
NSLog(@"objectId: %@", student.objectId);
NSLog(@"name: %@", [student objectForKey:@"name"]);
}];待验证:如果 Arrays 中包含多个课程,想知道一个课程选修的学生有多少,怎么查询,查询过程是怎样的?一对一关系当需要将一个对像拆分成两个对象时,一对一关系就会用到。下面的几个实例体现了这种需求:限制部分用户数据的权限:这个场景中,可以将对像拆分为两部分。一部分数据所有用户可见,另一部分数据仅自己可见;一部分数据所有用户可修改,另一部分数据仅自己可修改。避免大对象:原始对像大小如果超过 128 kb 上限值,可以通过创建另一个对象来存储额外的数据。文件对象:可以使用 AVObject 构建一个文件对象,并与 AVFile 建立一对一的关联,将文件属性存在 AVObject 中。通过这种方法既可以方便查询修改文件属性,也可以方便存取文件。关联数据的删除当表中有一 Pointer 或 Relation 指向的源数据被删除时,此源数据对应的 Pointer 或 Relation 不会被自动删除。基于业务场景如果有必要做数据清理的话,可以调用对象上的删除接口将 Pointer 或 Relation 关联的对象删除。
最新教程周点击榜
微信扫一扫

我要回帖

更多关于 leancloud 百度百科 的文章

 

随机推荐