查詢(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(玩數據)
