• 【TinyDB】查询


    查询(Query())

    数据存储格式

    1、默认使用JSON格式,只能处理简单类型的数据,自定义类肯定搞不定。

    2、如果出现了问题,可以自己写存储格式,可以变得更强大但是也更慢。

    提示:如果多个TinyDB打开了同一个数据源(json文件),在用Query()查询是会意外。

     1、ORM语法

    开始不太懂,自己查了下:

    ORM:对象关系映射(Object Relational Mapping,简称ORM),
    目的是想像操作对象一样操作数据库.因为数据库不是面向对象的,所以需要编程进行映射.

    1.1 基本操作

    这里要使用上一节代码跑完后生成的  db.json 文件。

    前提条件是:实例化一个TinyDB()对象 db = TinyDB('db.json') 和一个Query()对象 User = Query() 

    db = TinyDB('db.json')
    User = Query()
    a = db.search(User.name == 'John')
    print(a) # [{'name': 'John', 'age': 22}]

    入门里面已经讲了,记得代码里面还可用中文。

    1.2 嵌套查询

    如果字典里面key对应的value也是字典怎么办?这种情况应该还是蛮常见的。

    db.insert({'湖北':{'宜昌':'0717'}})  # 新增一个这种情况
    b = db.search(User.湖北.宜昌 == '0717') # 嵌套就是继续在后面加'.'
    print(b) # [{'湖北': {'宜昌': '0717'}}] 

    1.3 特殊情况

    如果要查询的键里面含有python解释器不能当成映射的符号怎么办?比如:  + - * / %  

    db.insert({'1+1':'2'})
    c = db.search(User['1+1'] == '2') 那就只能用这种方法,
    print(c) #[{'1+1': '2'}]

    1.4 where方法

    这是一种简化的方法,先看代码:

    from tinydb import where  # 要先导入where
    d = db.search(where('name')=='John')
    e = db.search(Query()['name']=='John')
    print(d) # [{'name': 'John', 'age': 22}]
    print(e) # [{'name': 'John', 'age': 22}]

    发现这两个东西结果是一样的。结果代码导航后一看,源码里面赫然写着:

    def where(key):
      return Query()[key]

    它就是这么写的,按照这个思路,还可以再扩展下。我如果想直接拿到具体的文字,而不是查询所返回的列表:

    from tinydb import TinyDB, where
    
    db = TinyDB('test.json')
    db.insert({'名字':'张三','分数':'100'})
    db.insert({'名字':'李四','分数':'98'})
    
    def get_data(db,index_a, val, index_b ):
        print(db.search(where(index_a)== val)[0][index_b]) #这个[0]不能少
    
    get_data(db,'名字', '张三', '分数') # 100
    get_data(db,'分数', '100', '名字') # 张三

    扯远了,刚才往后翻了下,居然真的还有个TinyDB自带的类似方法:  db.get(...) 。后面再讲,它有特定的使用条件。

     Query() 有嵌套,那说明 where() 应该也有嵌套,毕竟 where(key) = Query()[key] 

    #使用where()对字段进行嵌套查询
    db.insert({'birthday':{'year':1999,'month':'Sep','day': 11}})
    f = db.search(where('birthday').year == 1999)
    g = db.search(where('birthday')['year'] == 1999)
    print(f) # [{'birthday': {'year': 1999, 'month': 'Sep', 'day': 11}}]
    print(g) # [{'birthday': {'year': 1999, 'month': 'Sep', 'day': 11}}]

    上面两种方式都可以。

    2、高级查询

    2.1 判断是否存在 exist(...) ,返回对于字段列表(filed)

    h = db.search(User.name.exists())
    print(h) # [{'name': 'John', 'age': 22}, {'name': 'sheet', 'age': 23}]

    2.2 正则表达式判断 matches(...) 

    i = db.search(User.name.matches('[aZ]*'))
    print(i) # [{'name': 'John', 'age': 22}, {'name': 'sheet', 'age': 23}]

    但是我的正则学的不好,早就忘记了,没关系,还有更屌的!

    import re
    j = db.search(User.name.matches('John', flags=re.IGNORECASE))
    print(j)  # [{'name': 'John', 'age': 22}]

    直接用value值‘John’去匹配他的key,也就是'name'。

    那如果value值很长,记不住怎么办?

    没关系,还支持使用首字符查询。首字符可以,前n个字符都可以,中间的切片不行。

    那如果value值是个字典,怎么办?

    没关系,还支持使用嵌套的方法。

    db.insert({'中国':'湖北省','武汉':{'继续':'加油'}})
    l = db.search(User.中国.matches('湖北', flags=re.IGNORECASE))
    l_1 = db.search(User.中国.matches('', flags=re.IGNORECASE))
    l_2 = db.search(User.中国.matches('', flags=re.IGNORECASE))
    # value也是字典的话,只能嵌套查询
    m = db.search(User.武汉.matches('加油', flags=re.IGNORECASE)) 
    n = db.search(User.武汉.继续.matches('', flags=re.IGNORECASE))
    print(l) #[{'中国': '湖北省', '武汉': {'继续': '加油'}}]
    print(l_1) #[{'中国': '湖北省', '武汉': {'继续': '加油'}}]
    print(l_2) # []
    print(m) # []
    print(n) # [{'中国': '湖北省', '武汉': {'继续': '加油'}}]

    我觉得这个就有点太NB了。

    2.3 自定义查询 test(...) 

    自己可以写一段用来判断的函数,直接作为判断条件进行使用。分带参数和不带参数两种。

    # 不带参数
    test_func = lambda s:s == 'John' o = db.search(User.name.test(test_func)) print(o) # [{'name': 'John', 'age': 22}] # 带参数 def test_func1(val, m, n): return m <= val <= n p = db.search(User.age.test(test_func1,2,40)) print(p) #[{'name': 'John', 'age': 22}, {'name': 'sheet', 'age': 23}]

     2.3 字段里面包含列表时 any(...)  all(...) 

    上面说字段是字典时,可以嵌套查询,那如果是个列表,总不能用数字吧,比如: list[0] 。万不得已我觉得也可以。但是有更好的办法。

    db.insert({'name': 'user1', 'groups': ['user']})
    db.insert({'name': 'user2', 'groups': ['admin', 'user']})
    db.insert({'name': 'user3', 'groups': ['sudo', 'user']})
    
    # any():只要'groups'对应的值中在['admin','sudo']里面出现,都会返回
    q = db.search(User.groups.any(['admin','sudo']))
    # all():完全符合查询条件['admin','user']的,才会被返回
    r = db.search(User.groups.all(['admin','user']))print(q) # [{'name': 'user2', 'groups': ['admin', 'user']}, {'name': 'user3', 'groups': ['sudo', 'user']}]
    print(r) # [{'name': 'user2', 'groups': ['admin', 'user']}]

    但是如果列表的元素不是字符串,而是字典的时候,就比较麻烦了。需要用多重查询。

    多重查询给列表里面的字典再实例一个 Query() 

    # 多重查询,用两个Query()实例去嵌套查询
    G = Query()
    P = Query()
    groups = db.table('groups') # 现在db里面有两张表,'-default'和'groups'
    #db相当于 db.table('_default'),我们现在要查询的是db.table('groups')
    groups.insert({
            'name': 'user',
            'permissions': [{'type': 'read'}]})
    groups.insert({
            'name': 'sudo',
            'permissions': [{'type': 'read'}, {'type': 'sudo'}]})
    groups.insert({
            'name': 'admin',
            'permissions': [{'type': 'read'}, {'type': 'write'}, {'type': 'sudo'}]})
    
    # 任意符合P.type == 'read'条件的都返回
    s = groups.search(G.permissions.any(P.type == 'read'))
    print(s) #[{'name': 'user', 'permissions': [{'type': 'read'}]}, 
           {'name': 'sudo', 'permissions': [{'type': 'read'}, {'type': 'sudo'}]},
           {'name': 'admin', 'permissions': [{'type': 'read'}, {'type': 'write'}, {'type': 'sudo'}]}]
    # 完全符合P.type == 'read'条件的才返回,方法名字如果换成 only可能更好理解
    t = groups.search(G.permissions.all(P.type == 'read'))
    print(t) # [{'name': 'user', 'permissions': [{'type': 'read'}]}]

     还是使用 any(...) 和 all(...) 方法。总结哈:

     any([...]) 是任意匹配,只要列表里面有一项能匹配到,就会返回。

     all([...]) 是全部匹配,只有列表里面全部都能匹配到,才会返回。

    The opposite operation, checking if a single item is contained in a list, is also possible using :one_of

    这个地方没搞太明白,我的理解是,只针对 db.insert({'name':'john'})  这样的简单形式,新增的字段里面,不嵌套列表和字典。那么可以用 one_of([...]) 。只要 [...] 有元素是 'john' ,那就返回。

    db.search(User.name.one_of(['jane', 'john']))

    3、修饰符(~,&,|)

    print(db.search(~ (User.name == 'John'))) # 非
    print(db.search((User.name == 'John') & (User.age <= 30))) #且
    print(db.search((User.name == 'John') | (User.name == 'Bob'))) #或

    4、记住这张表

    Queries
    Query().field.exists() 判断是否存在
    Query().field.matches(regex) 使用正则表达式查询
    Query().field.search(regex) 按指定的条件去查询
    Query().field.test(func,*args) 自定义查询
    Query().field.all(query|list) 任意匹配,只要列表里面有一项能匹配到,就会返回。
    Query().field.any(query|list) 全部匹配,只有列表里面全部都能匹配到,才会返回。
    Query().field.one_of(list) Match if the field is contained in the list
    Logical operations on queries
    (query)
    (query1) (query2)
    (query1) (query2)

    上一节:TinyDB(入门)

    下一节:TinyDB(玩数据)

  • 相关阅读:
    String与其他类型的转换
    Java并发(5):同步容器
    Java并发(4):ThreadLocal
    Java并发(2):Lock
    Java并发(1):synchronized
    Java并发之——线程池
    每天一个设计模式(7):单例模式
    Java集合(9):ConcurrentHashMap
    10 常用端口和Web 页面请求过程
    9 应用协议
  • 原文地址:https://www.cnblogs.com/watalo/p/12388046.html
Copyright © 2020-2023  润新知