mlmongo 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mlmongo/__init__.py +1 -0
- mlmongo/asyncs.py +150 -0
- mlmongo/sync.py +121 -0
- mlmongo-1.0.0.dist-info/METADATA +19 -0
- mlmongo-1.0.0.dist-info/RECORD +7 -0
- mlmongo-1.0.0.dist-info/WHEEL +5 -0
- mlmongo-1.0.0.dist-info/top_level.txt +1 -0
mlmongo/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .sync import Mongoer, MongoerChild
|
mlmongo/asyncs.py
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from typing import Any,AsyncGenerator
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
try:
|
|
5
|
+
from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorCollection
|
|
6
|
+
except:
|
|
7
|
+
raise ModuleNotFoundError('pip install motor')
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _limit(afunc):
|
|
11
|
+
async def _main(self:'AMongoer', *args, **kwargs):
|
|
12
|
+
async with self._sem:
|
|
13
|
+
return await afunc(self, *args, **kwargs)
|
|
14
|
+
|
|
15
|
+
return _main
|
|
16
|
+
|
|
17
|
+
def _limit_iterator(afunc):
|
|
18
|
+
async def _main(self:'AMongoer', *args, **kwargs):
|
|
19
|
+
async with self._sem:
|
|
20
|
+
async for result in afunc(self, *args, **kwargs):
|
|
21
|
+
yield result
|
|
22
|
+
|
|
23
|
+
return _main
|
|
24
|
+
|
|
25
|
+
class AMongoer:
|
|
26
|
+
def __init__(self, url:str, default_db:str, default_col:str, default_key_name:str=None, async_limit:int=300):
|
|
27
|
+
self.url = url
|
|
28
|
+
self.client=None
|
|
29
|
+
self.default_db=default_db
|
|
30
|
+
self.default_col=default_col
|
|
31
|
+
self.default_key_name=default_key_name
|
|
32
|
+
self._sem = asyncio.BoundedSemaphore(async_limit)
|
|
33
|
+
|
|
34
|
+
def _getClient(self):
|
|
35
|
+
client = AsyncIOMotorClient(self.url)
|
|
36
|
+
client.get_io_loop = asyncio.get_running_loop
|
|
37
|
+
return client
|
|
38
|
+
|
|
39
|
+
def getConnect(self, db: str=None, col:str=None)->AsyncIOMotorCollection:
|
|
40
|
+
if self.client is None: self.client=self._getClient()
|
|
41
|
+
return self.client[db or self.default_db][col or self.default_col]
|
|
42
|
+
|
|
43
|
+
async def client_reset(self):
|
|
44
|
+
if self.client: self.client.close()
|
|
45
|
+
self.client = self._getClient()
|
|
46
|
+
|
|
47
|
+
async def client_auto_reset(self, s=600):
|
|
48
|
+
while True:
|
|
49
|
+
await asyncio.sleep(s)
|
|
50
|
+
self.client.close()
|
|
51
|
+
self.client = self._getClient()
|
|
52
|
+
|
|
53
|
+
@_limit
|
|
54
|
+
async def find(self, query: dict, db:str=None, col:str=None, cig:dict=None, default_id:int=0)->dict|None:
|
|
55
|
+
if default_id==0: cig = {'_id':0, **cig} if cig else {'_id':0}
|
|
56
|
+
result = await self.getConnect(db,col).find_one(query or {}, cig or {})
|
|
57
|
+
return result
|
|
58
|
+
|
|
59
|
+
@_limit_iterator
|
|
60
|
+
async def find_all(self, query: dict=None, db:str=None, col:str=None, cig=None,
|
|
61
|
+
sort_map: dict[str, int]=None, skip:int=None, limit:int=None)->AsyncGenerator[dict, None]:
|
|
62
|
+
cursor = self.getConnect(db,col).find(query, {'_id':0, **cig} if cig else {'_id':0})
|
|
63
|
+
if sort_map: cursor=cursor.sort(sort_map)
|
|
64
|
+
if skip: cursor=cursor.skip(skip)
|
|
65
|
+
if limit: cursor=cursor.limit(limit)
|
|
66
|
+
async for dt in cursor:
|
|
67
|
+
yield dt
|
|
68
|
+
|
|
69
|
+
@_limit
|
|
70
|
+
async def find_onekey_all(self, key:str, query: dict=None, db:str=None, col:str=None)->list:
|
|
71
|
+
cursor = self.getConnect(db,col).find(query, {'_id':0, key:1})
|
|
72
|
+
return [dt[key] async for dt in cursor]
|
|
73
|
+
|
|
74
|
+
@_limit
|
|
75
|
+
async def find_onecol(self, key:str, query: dict, db:str=None, col:str=None, default=None):
|
|
76
|
+
dt = (await self.getConnect(db,col).find_one(query, {'_id':0, key:1})) or {}
|
|
77
|
+
return dt.get(key, default)
|
|
78
|
+
|
|
79
|
+
@_limit
|
|
80
|
+
async def count(self, query: dict=None, db:str=None, col:str=None)->int:
|
|
81
|
+
return await self.getConnect(db,col).count_documents(query)
|
|
82
|
+
|
|
83
|
+
@_limit
|
|
84
|
+
async def update_one(self, query: dict, data: BaseModel|dict, db:str=None, col:str=None, upsert=True)->dict:
|
|
85
|
+
return (await self.getConnect(db,col).update_one(query, {'$set': data.model_dump() if isinstance(data,BaseModel) else data}, upsert=upsert)).raw_result
|
|
86
|
+
|
|
87
|
+
@_limit
|
|
88
|
+
async def update_by_id(self, id:Any, data:BaseModel|dict, db:str=None, col:str=None, upsert=True, key_name:str=None):
|
|
89
|
+
assert key_name or self.default_key_name, '没有设置key_name'
|
|
90
|
+
return await self.update_one({key_name or self.default_key_name:id}, data, db=db, col=col, upsert=upsert)
|
|
91
|
+
|
|
92
|
+
@_limit
|
|
93
|
+
async def update(self, query: dict, dt:dict, db:str=None, col:str=None)->dict:
|
|
94
|
+
return (await self.getConnect(db,col).update_many(query, {'$set': dt})).raw_result
|
|
95
|
+
|
|
96
|
+
@_limit
|
|
97
|
+
async def del_field(self, query: dict, *fields: str, db:str=None, col:str=None)->dict:
|
|
98
|
+
assert fields
|
|
99
|
+
return (await self.getConnect(db,col).update_many(query, {'$unset':{f:'' for f in fields}})).raw_result
|
|
100
|
+
|
|
101
|
+
@_limit
|
|
102
|
+
async def pop(self, query: dict,db:str=None, col:str=None)->dict|None:
|
|
103
|
+
try:
|
|
104
|
+
dt = (await self.getConnect(db,col).find_one_and_delete(query)) or {}
|
|
105
|
+
dt.pop('_id', None)
|
|
106
|
+
return dt
|
|
107
|
+
except asyncio.exceptions.CancelledError as e:
|
|
108
|
+
raise e
|
|
109
|
+
except Exception as e:
|
|
110
|
+
return None
|
|
111
|
+
|
|
112
|
+
@_limit
|
|
113
|
+
async def insert(self, data: BaseModel|dict, db:str=None, col:str=None, **kwargs):
|
|
114
|
+
return await self.getConnect(db,col).insert_one(data.model_dump( **kwargs) if isinstance(data, BaseModel) else data)
|
|
115
|
+
|
|
116
|
+
@_limit
|
|
117
|
+
async def insert_many(self, datas: list[BaseModel|dict], db:str=None, col:str=None, **kwargs):
|
|
118
|
+
if not datas: return None
|
|
119
|
+
datas = [(data.model_dump(**kwargs) if isinstance(data, BaseModel) else data) for data in datas]
|
|
120
|
+
return await self.getConnect(db,col).insert_many(datas)
|
|
121
|
+
|
|
122
|
+
@_limit
|
|
123
|
+
async def delete(self, query: dict, db:str=None, col:str=None)->dict:
|
|
124
|
+
return (await self.getConnect(db,col).delete_many(query)).raw_result
|
|
125
|
+
|
|
126
|
+
def getChild(self, default_col:str)->'AMongoerChild':
|
|
127
|
+
return AMongoerChild(self, default_col)
|
|
128
|
+
|
|
129
|
+
class AMongoerChild(AMongoer):
|
|
130
|
+
def __init__(self, amer: AMongoer, default_col:str):
|
|
131
|
+
self._amer=amer
|
|
132
|
+
self.client=amer.client
|
|
133
|
+
self.default_db=amer.default_db
|
|
134
|
+
self.default_col=default_col
|
|
135
|
+
self.default_key_name=amer.default_key_name
|
|
136
|
+
self._sem = amer._sem
|
|
137
|
+
|
|
138
|
+
def _getClient(self):
|
|
139
|
+
self._amer.client = self._amer._getClient()
|
|
140
|
+
return self._amer.client
|
|
141
|
+
|
|
142
|
+
def getConnect(self, db: str=None, col:str=None)->AsyncIOMotorCollection:
|
|
143
|
+
if self.client is None: self.client=self._getClient()
|
|
144
|
+
return self.client[db or self.default_db][col or self.default_col]
|
|
145
|
+
|
|
146
|
+
async def client_reset(self):
|
|
147
|
+
raise ValueError('子类对象不能调用该方法')
|
|
148
|
+
|
|
149
|
+
async def client_auto_reset(self, **_):
|
|
150
|
+
raise ValueError('子类对象不能调用该方法')
|
mlmongo/sync.py
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from threading import Thread, Lock
|
|
3
|
+
import time
|
|
4
|
+
from typing import Any, Generator
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
from pymongo import MongoClient
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Mongoer:
|
|
10
|
+
def __init__(self, url:str, default_db:str, default_col:str, default_key_name:str=None):
|
|
11
|
+
self.url = url
|
|
12
|
+
self.client=None
|
|
13
|
+
self._lock = Lock()
|
|
14
|
+
self.default_db=default_db
|
|
15
|
+
self.default_col=default_col
|
|
16
|
+
self.default_key_name=default_key_name
|
|
17
|
+
|
|
18
|
+
def _getClient(self):
|
|
19
|
+
client = MongoClient(self.url)
|
|
20
|
+
return client
|
|
21
|
+
|
|
22
|
+
def getConnect(self, db: str=None, col:str=None):
|
|
23
|
+
if self.client is None:
|
|
24
|
+
with self._lock:
|
|
25
|
+
self.client=self._getClient()
|
|
26
|
+
return self.client[db or self.default_db][col or self.default_col]
|
|
27
|
+
|
|
28
|
+
def client_auto_reset(self, s=600):
|
|
29
|
+
def temp():
|
|
30
|
+
while True:
|
|
31
|
+
time.sleep(s)
|
|
32
|
+
with self._lock:
|
|
33
|
+
self.client.close()
|
|
34
|
+
self.client = self._getClient()
|
|
35
|
+
Thread(target=temp, daemon=True).start()
|
|
36
|
+
|
|
37
|
+
def find(self, query: dict, db:str=None, col:str=None, cig:dict=None, default_id:int=0)->dict|None:
|
|
38
|
+
if default_id==0: cig = {'_id':0, **cig} if cig else {'_id':0}
|
|
39
|
+
result = self.getConnect(db,col).find_one(query or {}, cig or {})
|
|
40
|
+
return result
|
|
41
|
+
|
|
42
|
+
def find_all(self, query: dict=None, db:str=None, col:str=None, cig=None,
|
|
43
|
+
sort_map: dict[str, int]=None, skip:int=None, limit:int=None)->Generator[dict, None, None]:
|
|
44
|
+
cursor = self.getConnect(db,col).find(query, {'_id':0, **cig} if cig else {'_id':0})
|
|
45
|
+
if sort_map: cursor=cursor.sort(sort_map)
|
|
46
|
+
if skip: cursor=cursor.skip(skip)
|
|
47
|
+
if limit: cursor=cursor.limit(limit)
|
|
48
|
+
for dt in cursor:
|
|
49
|
+
yield dt
|
|
50
|
+
|
|
51
|
+
def find_onekey_all(self, key:str, query: dict=None, db:str=None, col:str=None)->list:
|
|
52
|
+
cursor = self.getConnect(db,col).find(query, {'_id':0, key:1})
|
|
53
|
+
return [dt[key] for dt in cursor]
|
|
54
|
+
|
|
55
|
+
def find_onecol(self, key:str, query: dict=None, db:str=None, col:str=None, default=None):
|
|
56
|
+
dt = (self.getConnect(db,col).find_one(query, {'_id':0, key:1})) or {}
|
|
57
|
+
return dt.get(key, default)
|
|
58
|
+
|
|
59
|
+
def count(self, query: dict=None, db:str=None, col:str=None,)->int:
|
|
60
|
+
return self.getConnect(db,col).count_documents(query)
|
|
61
|
+
|
|
62
|
+
def update_one(self, query: dict, data: BaseModel|dict, db:str=None, col:str=None, upsert=True)->dict:
|
|
63
|
+
return self.getConnect(db,col).update_one(query, {'$set': data.model_dump() if isinstance(data,BaseModel) else data}, upsert=upsert).raw_result
|
|
64
|
+
|
|
65
|
+
def update_by_id(self, id:Any, data:BaseModel|dict, db:str=None, col:str=None, upsert=True, key_name:str=None):
|
|
66
|
+
assert key_name or self.default_key_name, '没有设置key_name'
|
|
67
|
+
return self.update_one({key_name or self.default_key_name:id}, data, db=db, col=col, upsert=upsert)
|
|
68
|
+
|
|
69
|
+
def update(self, query: dict, dt: dict, db:str=None, col:str=None)->dict:
|
|
70
|
+
return self.getConnect(db,col).update_many(query, {'$set': dt}).raw_result
|
|
71
|
+
|
|
72
|
+
def del_field(self, query: dict, *fields: str, db:str=None, col:str=None)->dict:
|
|
73
|
+
assert fields
|
|
74
|
+
return self.getConnect(db,col).update_many(query, {'$unset':{f:'' for f in fields}}).raw_result
|
|
75
|
+
|
|
76
|
+
def pop(self, query: dict,db:str=None, col:str=None)->dict|None:
|
|
77
|
+
try:
|
|
78
|
+
dt = self.getConnect(db,col).find_one_and_delete(query) or {}
|
|
79
|
+
dt.pop('_id', None)
|
|
80
|
+
return dt
|
|
81
|
+
except asyncio.exceptions.CancelledError as e:
|
|
82
|
+
raise e
|
|
83
|
+
except Exception as e:
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
def insert(self, data: BaseModel|dict, db:str=None, col:str=None, **kwargs):
|
|
87
|
+
return self.getConnect(db,col).insert_one(data.model_dump( **kwargs) if isinstance(data, BaseModel) else data)
|
|
88
|
+
|
|
89
|
+
def insert_many(self, datas: list[BaseModel|dict], db:str=None, col:str=None, **kwargs):
|
|
90
|
+
if not datas: return None
|
|
91
|
+
datas = [(data.model_dump(**kwargs) if isinstance(data, BaseModel) else data) for data in datas]
|
|
92
|
+
return self.getConnect(db,col).insert_many(datas)
|
|
93
|
+
|
|
94
|
+
def delete(self, query: dict, db:str=None, col:str=None)->dict:
|
|
95
|
+
return self.getConnect(db,col).delete_many(query).raw_result
|
|
96
|
+
|
|
97
|
+
def getChild(self, default_col:str)->'MongoerChild':
|
|
98
|
+
return MongoerChild(self, default_col)
|
|
99
|
+
|
|
100
|
+
class MongoerChild(Mongoer):
|
|
101
|
+
def __init__(self, mer: Mongoer, default_col:str):
|
|
102
|
+
self._amer=mer
|
|
103
|
+
self.client=mer.client
|
|
104
|
+
self.default_db=mer.default_db
|
|
105
|
+
self.default_col=default_col
|
|
106
|
+
self.default_key_name=mer.default_key_name
|
|
107
|
+
self._lock = mer._lock
|
|
108
|
+
|
|
109
|
+
def _getClient(self):
|
|
110
|
+
self._amer.client = self._amer._getClient()
|
|
111
|
+
return self._amer.client
|
|
112
|
+
|
|
113
|
+
def getConnect(self, db: str=None, col:str=None):
|
|
114
|
+
if self.client is None: self.client=self._getClient()
|
|
115
|
+
return self.client[db or self.default_db][col or self.default_col]
|
|
116
|
+
|
|
117
|
+
def client_reset(self):
|
|
118
|
+
raise ValueError('子类对象不能调用该方法')
|
|
119
|
+
|
|
120
|
+
def client_auto_reset(self, **_):
|
|
121
|
+
raise ValueError('子类对象不能调用该方法')
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mlmongo
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: mongodb数据库操作工具类
|
|
5
|
+
Home-page: https://www.python.org
|
|
6
|
+
Author: mengling
|
|
7
|
+
Author-email: 1321443305@qq.com
|
|
8
|
+
Requires-Python: >=3.8
|
|
9
|
+
Requires-Dist: pymongo
|
|
10
|
+
Requires-Dist: pydantic
|
|
11
|
+
Provides-Extra: all
|
|
12
|
+
Requires-Dist: motor; extra == "all"
|
|
13
|
+
Dynamic: author
|
|
14
|
+
Dynamic: author-email
|
|
15
|
+
Dynamic: home-page
|
|
16
|
+
Dynamic: provides-extra
|
|
17
|
+
Dynamic: requires-dist
|
|
18
|
+
Dynamic: requires-python
|
|
19
|
+
Dynamic: summary
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
mlmongo/__init__.py,sha256=cesH70lLQoM_qLpj9RBRTkfgCk1rZuWANL7a_92P1Yk,39
|
|
2
|
+
mlmongo/asyncs.py,sha256=4igFtzLh1d3pEsfFqGuJOBPAwYS70bXA6YJWOLmtGWs,6269
|
|
3
|
+
mlmongo/sync.py,sha256=wwTVAvDfSrr3MCHplsDiIQW-aWCe8S5MzZspHynvy3M,5282
|
|
4
|
+
mlmongo-1.0.0.dist-info/METADATA,sha256=amtm9RIdW4pU4T4NcOv0uwQ5_7MDuKuFl4TSj_sUFxk,448
|
|
5
|
+
mlmongo-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
6
|
+
mlmongo-1.0.0.dist-info/top_level.txt,sha256=0QntA4yS1rOX5C2b0qWL_c0VL1fooUWGAdnP6afYq0g,8
|
|
7
|
+
mlmongo-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
mlmongo
|