【python版】leanCloud的使用

17 篇文章 0 订阅
10 篇文章 0 订阅

【python版】leanCloud的使用

参考

通过凭证连接leanCloud

先配置leanCloud环境

pip install leancloud

首先进入 云服务控制台 > 设置 > 应用凭证,来获取 App IDApp Key 以及服务器地址,接着导入 leancloud,并调用 init 方法进行初始化:

# 参考 https://leancloud.cn/docs/sdk_setup-python.html, https://leancloud.github.io/python-sdk/

import leancloud

appId = 'Your appId'
appKey = 'Your appKey'
masterkey = "Your masterkey"

'''初始化'''
# lean_initialization = leancloud.init(appId, appKey)
lean_initialization = leancloud.init(appId, master_key=masterkey)
print(lean_initialization)  #None

'''开启调试日志'''
# 调试日志开启后,SDK 会把网络请求、错误消息等信息输出到 IDE 的日志窗口,
# 或是浏览器 Console 或是云引擎日志(如果在云引擎下运行 SDK)。
import logging
logging.basicConfig(level=logging.DEBUG)

'''验证'''
TestObject = leancloud.Object.extend('TestObject')  #派生一个新的 leancloud.Object 子类 TestObject
test_object = TestObject()
test_object.set('words', "Hello world!")    #在当前对象此字段(words)上赋值(Hello world!)
test_object.save()   #将对象数据保存至服务器

leanCloud的免费数据存储空间为1G,每天的API请求数 < 3万次,支持三个客户端同时在线

在这里插入图片描述

leanCloud对象(Object)

1、数据类型

  • leancloud.Object 支持的数据类型包括 String、Number、Boolean、Object、Array、Date 等等。你可以通过嵌套的方式在 Object 或 Array 里面存储更加结构化的数据。
  • leancloud.Object 还支持两种特殊的数据类型 Pointer 和 File,可以分别用来存储指向其他 leancloud.Object 的指针以及二进制数据。
  • leancloud.Object 同时支持 GeoPoint,可以用来存储地理位置信息。参见 GeoPoint。
bool = True
number = 2018
string = 'Top Hit Songs'
date = datetime.now()
list = [string, number]
dictionary = {
    'number': number,
    'string': string
}

比如对于下面这个对象信息,每个字段有着自己的数据类型:

在这里插入图片描述

2、构建并保存对象

构建对象

  • 在构建对象时,为了使云端知道对象属于哪个 class,需要将 class 的名字作为参数传入。
  • 你可以将云服务里面的 class 比作关系型数据库里面的表。一个 class 的名字必须以字母开头,且只能包含数字、字母和下划线

保存对象

  • 以下是一些对象的内置属性,会在对象保存时自动创建,无需手动指定:

    内置属性类型描述
    objectIdstr该对象唯一的 ID 标识
    ACLleancloud.ACL该对象的权限控制,实际上是一个 JSON 对象,控制台做了展现优化。
    createdAtdatetime.datetime该对象被创建的时间。
    updatedAtdatetime.datetime该对象最后一次被修改的时间。
  • 我们不推荐通过 byte[]leancloud.Object 里面存储图片、文档等大型二进制数据。
    每个 leancloud.Object 的大小不应超过 128 KB。如需存储大型文件,可创建 leancloud.File 实例并将将其关联到 leancloud.Object 的某个属性上。

代码整合如下:

class MyTest(unittest.TestCase):
    ''''''

    '''构建并保存对象'''
    def test_objectConstruct(self):
        ''''''
        '''
        Step3: 构建对象
        '''
        LoginUser = leancloud.Object.extend('LoginUser')  # 创建一个Object类((感觉)类似于rpc远程调用类对象,包装成代理类)
        loginUser = LoginUser()  # 实例化对象

        '''
        Step4: 保存对象
        '''
        loginUser.set("name", "wangxiaoxi")  # 为字段user赋值为wangxiaoxi
        loginUser.set("age", 25)
        loginUser.set("sex", "male")
        loginUser.set("marriaged", False)
        loginUser.save()  # 将对象数据保存至服务器

创建的LoginUser用户信息如下:

在这里插入图片描述

json格式如下(下面我都用json来展示数据效果):

在这里插入图片描述

3、获取对象(从创建到获取有时延)

通过objectId获取云端leanCloud对象,这里我们可以通过下面代码观察leanCloud对象各字段的返回类型。

还有要注意一点,对象从创建到获取存在时延,因此并不适合于实时性较强的任务,但可适用于即时通讯或者多人游戏作战。

'''获取对象'''
def test_getObject(self):
    '''
    Step5: 获取对象
        通过objectId获取云端leanCloud对象
    '''
    loginUser = leancloud.Object.extend('LoginUser')
    query = loginUser.query
    loginUser = query.get('62891f57033caa54ba63b1d6')
    # loginUser 就是 objectId 为 6288fda75e07a13788dcdbfd 的 LoginUser 实例
    name = loginUser.get('name')
    age = loginUser.get('age')
    sex = loginUser.get('sex')
    marriaged = loginUser.get('marriaged')

    # 获取内置属性
    object_id = loginUser.id
    update_at = loginUser.updated_at
    created_at = loginUser.created_at

    print(f"name = {name}, type = {type(name)}")
    print(f"age = {age}, type = {type(age)}")
    print(f"sex = {sex}, type = {type(sex)}")
    print(f"marriaged = {marriaged}, type = {type(marriaged)}")
    print(f"object_id = {object_id}, type = {type(object_id)}")
    print(f"update_at = {update_at}, type = {type(update_at)}")
    print(f"created_at = {created_at}, type = {type(created_at)}")

输出结果:

name = wangxiaoxi, type = <class 'str'>
age = 25, type = <class 'int'>
sex = male, type = <class 'str'>
marriaged = False, type = <class 'bool'>
object_id = 62891f57033caa54ba63b1d6, type = <class 'str'>
update_at = 2022-05-22 01:20:23.447000+08:00, type = <class 'datetime.datetime'>
created_at = 2022-05-22 01:20:23.447000+08:00, type = <class 'datetime.datetime'>

4、同步对象

'''同步对象'''
def test_synchronize_object(self):
    LoginUser = leancloud.Object.extend('LoginUser')
    loginUser = LoginUser.create_without_data('62891f57033caa54ba63b1d6')  #创建只封装ObjectId的对象
    loginUser.fetch()  #同步对象
    print(f'name = {loginUser.get("name")}')
    print(f'marriaged = {loginUser.get("marriaged")}')

输出结果:

name = wangxiaoxi
Ran 1 test in 0.264s

OK
marriaged = False

5、更新对象(可以创建新字段)

云服务会自动识别需要更新的属性并将对应的数据发往云端,未更新的属性会保持原样

'''更新对象'''
def test_update_object(self):
    ''''''
    LoginUser = leancloud.Object.extend('LoginUser')
    loginUser = LoginUser.create_without_data('62891f57033caa54ba63b1d6')  #创建只封装ObjectId的对象
    loginUser.set('marriaged', True)  #修改原有字段
    loginUser.set('balance', 1000)   #增加余额字段,余额1000元
    loginUser.set('friends', ['Ben'])   #增加friends字段,初始朋友有[Ben]
    loginUser.save()

以json格式保存的数据如下:

在这里插入图片描述

6、有条件更新对象(带where条件的save)

  • 通过传入 query 选项,可以按照指定条件去更新对象——当条件满足时,执行更新(save;条件不满足时,不执行更新并返回 305 错误。

  • 在统计一条微博的点赞转发次数时,由于赞和转发的操作可能由多个客户端同时进行,直接在本地更新数字并保存到云端的做法极有可能导致差错。为保证计数的准确性,可以通过 原子操作 来增加或减少一个属性内保存的数字(此过程并没有更新到云端):

    loginUser.increment('balance', amount)
    
  • 注意,虽然原子增减支持浮点数,但因为底层数据库的浮点数存储格式限制,会有舍入误差。

    因此,需要原子增减的字段建议使用整数以避免误差,例如 3.14 可以存储为 314,然后在客户端进行相应的转换。

    否则,以比较大小为条件查询对象的时候,需要特殊处理, < a 需改查 < a + e,> a 需改查 > a - e,== a 需改查 > a - e 且 < a + e,其中 e 为误差范围,据所需精度取值,比如 0.0001。

  • 在使用query创建where条件**时,要注意的是:

    query 选项只对已存在的对象有效,不适用于尚未存入云端的对象。
    多个客户端需要更新同一属性,相比于通过 leancloud.Query 查询 leancloud.Object 再对其进行更新的方法,这样做更加简洁,并且能够避免出现差错。

  • 一开始想用多线程来模拟多个客户端进行余额支出操作的,但是官网说:

    leancloud.Object 目前不是线程安全的,因此请避免多个线程修改同一个 leancloud.Object 实例的操作。如果遇到必须多线程操作的情况,需要根据情况加锁。

具体代码如下:

def test_update_object_withCondition(self):
      '''
      通过传入 query 选项,可以按照指定条件去更新对象——当条件满足时,执行更新;条件不满足时,不执行更新并返回 305 错误。
      '''
      LoginUser = leancloud.Object.extend("LoginUser")
      loginUser = LoginUser.create_without_data('6288fda75e07a13788dcdbfd')  #创建只封装ObjectId的对象
      # print(f'name = {loginUser.get("name")}')  #None
      # print(f'marriaged = {loginUser.get("marriaged")}')  #None
			

      amount = -300  # 支出300元
      loginUser.increment('balance', amount)  # 更新计时器,该操作 为原子操作
      # 设置条件:只有当查询的balance比消费金额大时,才可以完成消费
      where = loginUser.query.greater_than_or_equal_to('balance', -amount)
      '''
      @object.query  
      '''
      # 操作结束后,返回最新数据。
      # 如果是新对象,则所有属性都会被返回,
      # 否则只有更新的属性会被返回。
      loginUser.fetch_when_save = True
      try:
          loginUser.save(where=where)  #在保存对象前加入条件
          print('当前余额为:', loginUser.get('balance'))
      except leancloud.LeanCloudError as e:
          if e.code == 305:
              print('余额不足,操作失败!')
          else:
              raise

数据修改如下:

在这里插入图片描述

7、更新数组

更新数组也是原子操作。使用以下方法可以方便地维护数组类型的数据

  • add(): 将指定对象附加到数组末尾
  • add_unique(): 如果数组中不包含指定对象,则将该对象加入数组。对象的插入位置是随机的。
  • remove(): 从数组字段中删除指定对象的所有实例。
'''更新数组'''
def test_update_array(self):
    # 更新数组也是原子操作。使用以下方法可以方便地维护数组类型的数据
    friend1 = "Sarah"
    friend2 = "Lily"
    friend3 = "Lala"

    '''
        add(): 将指定对象附加到数组末尾
        add_unique(): 如果数组中不包含指定对象,则将该对象加入数组。对象的插入位置是随机的
        remove(): 从数组字段中删除指定对象的所有实例
    '''
    LoginUser = leancloud.Object.extend("LoginUser")
    loginUser = LoginUser.create_without_data('62891f57033caa54ba63b1d6')
    loginUser.add_unique('friends', friend1)
    loginUser.add_unique('friends', friend2)
    loginUser.add_unique('friends', friend3)
    loginUser.save()

效果如下:
在这里插入图片描述

8、删除对象

'''删除对象'''
def test_delete_object(self):
    LoginUser = leancloud.Object.extend('LoginUser')
    loginUser = LoginUser.create_without_data('62891f57033caa54ba63b1d6')
    loginUser.destroy()

9、批量操作

1)批量保存

leancloud.Object.save_all(list_of_objects)

'''批量save操作'''
def test_batch_save(self):
    ''''''
    LoginUser = leancloud.Object.extend("LoginUser")
    loginUser1 = LoginUser()
    loginUser2 = LoginUser()
    loginUser3 = LoginUser()

    loginUser1.set("name","Ben")
    loginUser2.set("name","Sarah")
    loginUser3.set("name","Lily")
    LoginUser.save_all([loginUser1,loginUser2,loginUser3])
2)批量删除

leancloud.Object.destroy_all(list_of_objects)

'''批量save操作'''
def test_batch_destroy(self):
    ''''''
    LoginUser = leancloud.Object.extend("LoginUser")
    loginUser1 = LoginUser.create_without_data("62890fec033caa54ba63ae7a")
    loginUser2 = LoginUser.create_without_data("62890fec033caa54ba63ae79")
    loginUser3 = LoginUser.create_without_data("62890fec033caa54ba63ae78")

    LoginUser.destroy_all([loginUser1, loginUser2, loginUser3])

10、对象关系

1)一对一、一对多关系
  • 一对一、一对多关系可以通过将 leancloud.Object 保存为另一个对象的属性值的方式产生。比如说,让博客应用中的一个 Comment 指向一个 Post (comment和post为多对一的关系)
  • 关于一对多数据的删除:并不需要进行级联删除,即如果删除掉post之后,comment虽然有Point属性指向该post,但是不会被删除。
'''数据类型:一对一,一对多关系'''
def test_relation1(self):
    ''''''
    '''
        一对一、一对多关系可以通过将 leancloud.Object 保存为另一个对象的属性值的方式产生。
        比如说,让博客应用中的一个 Comment 指向一个 Post (comment和post为多对一的关系)。
    '''
    # 创建 post
    Post = leancloud.Object.extend('Post')
    post = Post()
    post.set('title', '饿了……')
    post.set('content', '中午去哪吃呢?')

    # 创建 comment
    Comment = leancloud.Object.extend('Comment')
    comment = Comment()
    comment1 = Comment()
    comment.set('content', '当然是肯德基啦!')
    comment1.set('content', '当然是必胜客啦!')

    # 将 post 设为 comment 的一个属性值
    comment.set('parent', post)    #云端存储时,会将被指向的对象用 Pointer 的形式存起来。
    comment1.set('parent', post)
    # 保存 comment 会同时保存 post
    # Comment.save_all([comment,comment1])  #会报错:leancloud.errors.LeanCloudError: LeanCloudError: [106] Malformed pointer. Pointers must be maps of a classname and an object id.
    comment.save()
    comment1.save()

多对一对象创建效果如下:
在这里插入图片描述

删除代码如下:

'''关于一对多数据的删除'''
def test_relation1_destroy(self):
    Post = leancloud.Object.extend("Post")
    post = Post.create_without_data("62892f095e07a13788dce68a")
    post.destroy()  #删除post之后,与其绑定的comment并没有删除

删除效果演示:

在这里插入图片描述

2)多对多关系
  • 想要建立多对多关系,最简单的办法就是使用 数组。在大多数情况下,使用数组可以有效减少查询的次数,提升程序的运行效率。但如果有额外的属性需要附着于两个 class 之间的关联,那么使用 中间表 可能是更好的方式。
    注意这里说到的额外的属性是用来描述 class 之间的关系的,而不是任何单一的 class 的。
  • 我们建议你在任何一个 class 的对象数量超出 100 的时候考虑使用中间表。

leancloud.Object 目前不是线程安全的

leanCloud对象查询(Query)

下面这两种写法是一样的,都是创建关于Comment表的leanCloud.query.Query对象

#写法1
query = leanCloud.Query("Comment")  

#写法2
Comment = leanCloud.Object.extend("Comment")
query = Comment.query()

创建***Object.query()查询对象,用query.equal_to()等设置查询条件,用find()***进行查询

假设现在的LoginUser数据是这样的,共7条:

在这里插入图片描述

Comment数据,Post数据分别如下:

Comment:

在这里插入图片描述

Post:

在这里插入图片描述

1、基础查询

  • 构建 leancloud.Query;
  • 向其添加查询条件;
  • 执行查询并获取包含满足条件的对象的数组。
def repr(loginUser):
    print(f'loginUser:id = {loginUser.get("objectId")}, '
          f'name = {loginUser.get("name")}, '
          f'age = {loginUser.get("age")}, '
          f'marriaged = {loginUser.get("marriaged")}, '
          f'balance = {loginUser.get("balance")}, '
          f'friends = {loginUser.get("friends")}')

class MyTest(unittest.TestCase):

    '''基础查询'''
    def test_basic_query(self):
        ''''''
        '''
        基础查询: 创建Object.query查询对象,用equal_to设置查询条件,用find进行查询
            构建 leancloud.Query;
            向其添加查询条件;
            执行查询并获取包含满足条件的对象的数组。
        '''
        LoginUser = leancloud.Object.extend('LoginUser')
        query = LoginUser.query
        # 以上两行等价于 query = leancloud.Query('Student')
        query.equal_to('name', 'wangxiaoxi')
        loginUser_list = query.find()
        for loginUser in loginUser_list:
            repr(loginUser)

输出结果如下:

loginUser:id = 6289e80c5e07a13788dd0aa5, name = wangxiaoxi, age = 25, marriaged = True
loginUser:id = 6289e839033caa54ba63d5f3, name = wangxiaoxi, age = 25, marriaged = False
loginUser:id = 6289e83b033caa54ba63d5f5, name = wangxiaoxi, age = 25, marriaged = False

2、按条件查询

1)基本条件查询
  • not_equal_to: 不等于

  • less_than: 小于

  • less_than_or_equal_to: 不大于

  • greater_than: 大于

  • greater_than_or_equal_to: 不小于

2)设置多条件

在同一个查询中设置多个条件,这样可以获取满足所有条件的结果。可以理解为所有的条件是 AND 的关系

LoginUser = leancloud.Object.extend("LoginUser")
query = LoginUser.query
query.equal_to("name", 'wangxiaoxi')
query.equal_to('marriaged', True)  #已经结婚
query.greater_than_or_equal_to('balance', 1000)   #存款大于1000
print(repr(query.first()))

输出结果:

loginUser:id = 6289e80c5e07a13788dd0aa5, name = wangxiaoxi, age = 25, marriaged = True, balance = 1000
3)获取n条结果(limit)

由于性能原因,limit 最大只能设为 1000。即使将其设为大于 1000 的数,云端也只会返回 1,000 条结果。

#最多获取2条结果
query = leancloud.Query("LoginUser")
query.limit(2)
loginUsers = query.find()
print("limit find: ")
for loginUser in loginUsers:
    repr(loginUser)

输出结果:

limit find: 
loginUser:id = 6289e80c5e07a13788dd0aa5, name = wangxiaoxi, age = 25, marriaged = True, balance = 1000
loginUser:id = 6289e839033caa54ba63d5f3, name = wanghaoxi, age = 25, marriaged = False, balance = None
4)只获得第一条结果(first)
query = leancloud.Query("LoginUser")
loginUser = query.first()
print("first find: ")
repr(loginUser)

输出结果:

first find: 
loginUser:id = 6289e80c5e07a13788dd0aa5, name = wangxiaoxi, age = 25, marriaged = True, balance = 1000
5)跳过一定数量的结果(skip)
  • 把 skip 和 limit 结合起来,就能实现翻页功能
  • 需要注意的是,skip 的值越高,查询所需的时间就越长。作为替代方案,可以通过设置 createdAt 或 updatedAt 的范围来实现更高效的翻页,因为它们都自带索引。 同理,也可以通过设置自增字段的范围来实现翻页。
# 跳过前 2 条结果
query = leancloud.Query("LoginUser")
query.skip(2)
print("skip find: ")
loginUsers = query.find()
for loginUser in loginUsers:
    repr(loginUser)

输出结果:

loginUser:id = 6289e83b033caa54ba63d5f5, name = wangminxi, age = 25, marriaged = False, balance = None
loginUser:id = 6289e83e033caa54ba63d5f6, name = Lily, age = 25, marriaged = False, balance = None
loginUser:id = 6289e8405e07a13788dd0ab0, name = Tom, age = 25, marriaged = False, balance = None
loginUser:id = 6289e843033caa54ba63d5f8, name = Ben, age = 25, marriaged = False, balance = None
loginUser:id = 6289e845033caa54ba63d5fa, name = Sarah, age = 25, marriaged = False, balance = None
6)按属性排序(add_descending)

可以为同一个查询添加多个排序规则:

'''
Step4: 属性排序
'''
query = leancloud.Query("LoginUser")
# # 按 createdAt 升序排列
# query.ascending('createdAt')
#
# # 按 createdAt 降序排列
# query.descending('createdAt')

'''为同一个查询添加多个排序规则;'''
query.add_ascending('marriaged')
query.add_descending('name')
loginUsers = query.find()
for loginUser in loginUsers:
    repr(loginUser)

输出结果

loginUser:id = 6289e839033caa54ba63d5f3, name = wanghaoxi, age = 25, marriaged = False, balance = None
loginUser:id = 6289e845033caa54ba63d5fa, name = Sarah, age = 25, marriaged = False, balance = None
loginUser:id = 6289e83e033caa54ba63d5f6, name = Lily, age = 25, marriaged = False, balance = None
loginUser:id = 6289e843033caa54ba63d5f8, name = Ben, age = 25, marriaged = False, balance = None
loginUser:id = 6289e80c5e07a13788dd0aa5, name = wangxiaoxi, age = 25, marriaged = True, balance = 1000
loginUser:id = 6289e83b033caa54ba63d5f5, name = wangminxi, age = 25, marriaged = True, balance = None
loginUser:id = 6289e8405e07a13788dd0ab0, name = Tom, age = 25, marriaged = True, balance = None
7)查找包含或不包含某一属性的对象(exist)
  • 包含该属性的对象:query.exists()
  • 不包含该属性的对象(该属性对象为空):query.does_not_exist()
query = leancloud.Query("LoginUser")
# 查找包含 'friends' 的对象
query.exists('friends')
# 查找不包含 'friends' 的对象
# query.does_not_exist('friends')
loginUsers = query.find()
for loginUser in loginUsers:
    repr(loginUser)

输出结果:

loginUser:id = 6289e80c5e07a13788dd0aa5, name = wangxiaoxi, age = 25, marriaged = True, balance = 1000
8)返回指定需要的属性(select)

通过 select 指定需要返回的属性。下面的代码只获取每个对象的 name 和 age
(包括内置属性 objectId、createdAt 和 updatedAt)

LoginUser = leancloud.Object.extend('LoginUser')
query = LoginUser.query
query.select('name', 'age')
loginUsers = query.find()
for loginUser in loginUsers:
    repr(loginUser)

# title = todo.get('name')  # √
# content = todo.get('age')  # √
# notes = todo.get('sex')  # None
print(repr(loginUser))

输出结果,未指定的属性输出结果为None:

loginUser:id = 6289e83b033caa54ba63d5f5, name = wangminxi, age = 25, marriaged = None, balance = None
loginUser:id = 6289e83e033caa54ba63d5f6, name = Lily, age = 25, marriaged = None, balance = None
loginUser:id = 6289e8405e07a13788dd0ab0, name = Tom, age = 25, marriaged = None, balance = None
loginUser:id = 6289e843033caa54ba63d5f8, name = Ben, age = 25, marriaged = None, balance = None
loginUser:id = 6289e845033caa54ba63d5fa, name = Sarah, age = 25, marriaged = None, balance = None
loginUser:id = 6289e845033caa54ba63d5fa, name = Sarah, age = 25, marriaged = None, balance = None

3、按字符串查询(模糊查询)

1)查询Keyword开头的内容

可以用 startswith 来查找某一属性值以特定字符串开头的对象。和 SQL 中的 LIKE 一样,你可以利用索引带来的优势。

LoginUser = leancloud.Object.extend('LoginUser')
query = LoginUser.query
# 相当于 SQL 中的 name LIKE 'wang%'
query.startswith("name", "wang")
loginUsers = query.find()
	  for loginUser in loginUsers:
	      repr(loginUser)

输出结果:

loginUser:id = 6289e80c5e07a13788dd0aa5, name = wangxiaoxi, age = 25, marriaged = True, balance = 1000
loginUser:id = 6289e839033caa54ba63d5f3, name = wanghaoxi, age = 25, marriaged = False, balance = None
loginUser:id = 6289e83b033caa54ba63d5f5, name = wangminxi, age = 25, marriaged = True, balance = None
2)查询包含Keyword的内容
  • 可以用 contains 来查找某一属性值包含特定字符串的对象
  • startswith 不同,contains 无法利用索引,因此不建议用于大型数据集。
  • 注意 startswithcontains 都是 区分大小写
LoginUser = leancloud.Object.extend('LoginUser')
query = LoginUser.query
# 相当于 SQL 中的 name LIKE '%wang%'
query.contains("name", "wang")
loginUsers = query.find()
for loginUser in loginUsers:
    repr(loginUser)

输出结果

loginUser:id = 6289e80c5e07a13788dd0aa5, name = wangxiaoxi, age = 25, marriaged = True, balance = 1000
loginUser:id = 6289e839033caa54ba63d5f3, name = wanghaoxi, age = 25, marriaged = False, balance = None
loginUser:id = 6289e83b033caa54ba63d5f5, name = wangminxi, age = 25, marriaged = True, balance = None

4、数组查询

1)按数组中某个对象进行查询
'''Step1: 下面的代码查找所有数组属性 friends 包含 Ben 的对象'''
LoginUser = leancloud.Object.extend("LoginUser")
query = LoginUser.query  #leanCLoud.query.Query对象
query.equal_to("friends",'Ben')
loginUsers = query.find()
for loginUser in loginUsers:
    repr(loginUser)

输出结果:

loginUser:id = 6289e80c5e07a13788dd0aa5, name = wangxiaoxi, age = 25, marriaged = True, balance = 1000, friends = ['Ben', 'Lily', 'Sarah', 'Lala']
loginUser:id = 6289e843033caa54ba63d5f8, name = Ben, age = 25, marriaged = False, balance = None, friends = ['Ben', 'Lily']
loginUser:id = 6289e845033caa54ba63d5fa, name = Sarah, age = 25, marriaged = False, balance = None, friends = ['Ben']
2)按数组长度进行查询
LoginUser = leancloud.Object.extend("LoginUser")
query = LoginUser.query
query.size_equal_to("friends", 4)
loginUsers = query.find()
for loginUser in loginUsers:
    repr(loginUser)

输出结果:

loginUser:id = 6289e80c5e07a13788dd0aa5, name = wangxiaoxi, age = 25, marriaged = True, balance = 1000, friends = ['Ben', 'Lily', 'Sarah', 'Lala']
3)按数组中包含的对象列表进行查询
LoginUser = leancloud.Object.extend("LoginUser")
query = LoginUser.query
query.contains_all("friends", ['Ben','Lily'])
loginUsers = query.find()
for loginUser in loginUsers:
    repr(loginUser)

输出结果:

loginUser:id = 6289e80c5e07a13788dd0aa5, name = wangxiaoxi, age = 25, marriaged = True, balance = 1000, friends = ['Ben', 'Lily', 'Sarah', 'Lala']
loginUser:id = 6289e843033caa54ba63d5f8, name = Ben, age = 25, marriaged = False, balance = None, friends = ['Ben', 'Lily']

5、关系查询

1)查询某一博客(post)下的所有评论(comment)
def repr_comments(comment):
    print(f'comment:id = {comment.get("objectId")}, '
          f'content = {comment.get("content")}, '
          f'post.content = {comment.get("parent").get("content")}, '
          f'post.title = {comment.get("parent").get("title")}, '
          f'post.images = {comment.get("parent").get("images")}')

'''关系查询1'''
def test_query_with_relations(self):
    ''''''
    '''
    查询关联数据有很多种方式,常见的一种是查询某一属性值为特定 leancloud.Object 的对象,这时可以像其他查询一样直接用 equal_to。
    比如说,如果每一条博客评论 Comment 都有一个 post 属性用来存放原文 Post,则可以用下面的方法获取所有与某一 Post 相关联的评论:
    '''
    Post = leancloud.Object.extend('Post')
    post = Post.create_without_data('628a09785e07a13788dd10a4')
    query = leancloud.Query('Comment')   #获取关于Comment对象的查询, 即leanCLoud.query.Query对象
    query.equal_to('parent', post)
    comment_list = query.find()
    for comment in comment_list:
        repr_comments(comment)

输出结果:

comment:id = 628a09785e07a13788dd10a5, content = 当然是肯德基啦!, post.content = None, post.title = None, post.images = None
comment:id = 628a0978033caa54ba63dba9, content = 当然是必胜客啦!, post.content = None, post.title = None, post.images = None
2)查询可以找到所有包含图片的博客(post)文章的评论(comment)

云端使用的并非关系型数据库,无法做到真正的联表查询,所以实际的处理方式是:

  • 先执行内嵌/子查询(和普通查询一样,limit 默认为 100,最大 1000),
  • 然后将子查询的结果填入主查询的对应位置,再执行主查询。
  • 如果子查询匹配到的记录数量超出 limit,且主查询有其他查询条件,那么可能会出现没有结果或结果不全的情况,因为只有 limit 数量以内的结果会被填入主查询。
'''关系查询2'''
def test_query_with_relations1(self):
    ''''''
    '''
    如需获取某一属性值为另一查询结果中任一 leancloud.Object 的对象,可以用 matches_query。
    下面的代码构建的查询可以找到所有包含图片的博客文章的评论:
    '''
    inner_query = leancloud.Query('Post')
    inner_query.exists('images')

    query = leancloud.Query('Comment')
    query.matches_query('parent', inner_query)  #通过Comment表的leanCLoud.query.Query对象,选择包含images属性的post
    comment_list = query.find()
    for comment in comment_list:
        repr_comments(comment)

输出结果:

comment:id = 628a0cf15e07a13788dd112d, content = 看日出..., post.content = None, post.title = None, post.images = None
comment:id = 628a0cf1033caa54ba63dcab, content = 谁不是个月光族呢, post.content = None, post.title = None, post.images = None

6、统计总数量

'''统计总数量'''
def test_get_count(self):
    LoginUser = leancloud.Object.extend('LoginUser')
    query = LoginUser.query
    query.equal_to('marriaged', True)
    count = query.count()
    print(f"marriaged count = {count}")

输出结果:

marriaged count = 3
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值