3 from pymongo
import MongoClient
, errors
4 from dbbase
import DbException
, DbBase
5 from http
import HTTPStatus
6 from time
import time
, sleep
8 __author__
= "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
11 class DbMongo(DbBase
):
12 conn_initial_timout
= 120
15 def __init__(self
, logger_name
='db'):
16 self
.logger
= logging
.getLogger(logger_name
)
18 def db_connect(self
, config
):
20 if "logger_name" in config
:
21 self
.logger
= logging
.getLogger(config
["logger_name"])
22 self
.client
= MongoClient(config
["host"], config
["port"])
23 self
.db
= self
.client
[config
["name"]]
24 if "loglevel" in config
:
25 self
.logger
.setLevel(getattr(logging
, config
['loglevel']))
26 # get data to try a connection
30 self
.db
.users
.find_one({"username": "admin"})
32 except errors
.ConnectionFailure
as e
:
33 if time() - now
>= self
.conn_initial_timout
:
35 self
.logger
.info("Waiting to database up {}".format(e
))
37 except errors
.PyMongoError
as e
:
38 raise DbException(str(e
))
40 def db_disconnect(self
):
44 def _format_filter(filter):
47 for query_k
, query_v
in filter.items():
48 dot_index
= query_k
.rfind(".")
49 if dot_index
> 1 and query_k
[dot_index
+1:] in ("eq", "ne", "gt", "gte", "lt", "lte", "cont",
51 operator
= "$" + query_k
[dot_index
+1:]
52 if operator
== "$neq":
54 k
= query_k
[:dot_index
]
60 if isinstance(v
, list):
61 if operator
in ("$eq", "$cont"):
64 elif operator
in ("$ne", "$ncont"):
70 if operator
in ("$eq", "$cont"):
71 # v cannot be a comma separated list, because operator would have been changed to $in
73 elif operator
== "$ncount":
74 # v cannot be a comma separated list, because operator would have been changed to $nin
75 db_filter
[k
] = {"$ne": v
}
77 # maybe db_filter[k] exist. e.g. in the query string for values between 5 and 8: "a.gt=5&a.lt=8"
78 if k
not in db_filter
:
80 db_filter
[k
][operator
] = v
83 except Exception as e
:
84 raise DbException("Invalid query string filter at {}:{}. Error: {}".format(query_k
, v
, e
),
85 http_code
=HTTPStatus
.BAD_REQUEST
)
88 def get_list(self
, table
, filter={}):
91 collection
= self
.db
[table
]
92 rows
= collection
.find(self
._format
_filter
(filter))
98 except Exception as e
: # TODO refine
99 raise DbException(str(e
))
101 def get_one(self
, table
, filter={}, fail_on_empty
=True, fail_on_more
=True):
104 filter = self
._format
_filter
(filter)
105 collection
= self
.db
[table
]
106 if not (fail_on_empty
and fail_on_more
):
107 return collection
.find_one(filter)
108 rows
= collection
.find(filter)
109 if rows
.count() == 0:
111 raise DbException("Not found entry with filter='{}'".format(filter), HTTPStatus
.NOT_FOUND
)
113 elif rows
.count() > 1:
115 raise DbException("Found more than one entry with filter='{}'".format(filter),
118 except Exception as e
: # TODO refine
119 raise DbException(str(e
))
121 def del_list(self
, table
, filter={}):
123 collection
= self
.db
[table
]
124 rows
= collection
.delete_many(self
._format
_filter
(filter))
125 return {"deleted": rows
.deleted_count
}
128 except Exception as e
: # TODO refine
129 raise DbException(str(e
))
131 def del_one(self
, table
, filter={}, fail_on_empty
=True):
133 collection
= self
.db
[table
]
134 rows
= collection
.delete_one(self
._format
_filter
(filter))
135 if rows
.deleted_count
== 0:
137 raise DbException("Not found entry with filter='{}'".format(filter), HTTPStatus
.NOT_FOUND
)
139 return {"deleted": rows
.deleted_count
}
140 except Exception as e
: # TODO refine
141 raise DbException(str(e
))
143 def create(self
, table
, indata
):
145 collection
= self
.db
[table
]
146 data
= collection
.insert_one(indata
)
147 return data
.inserted_id
148 except Exception as e
: # TODO refine
149 raise DbException(str(e
))
151 def set_one(self
, table
, filter, update_dict
, fail_on_empty
=True):
153 collection
= self
.db
[table
]
154 rows
= collection
.update_one(self
._format
_filter
(filter), {"$set": update_dict
})
155 if rows
.updated_count
== 0:
157 raise DbException("Not found entry with filter='{}'".format(filter), HTTPStatus
.NOT_FOUND
)
159 return {"deleted": rows
.deleted_count
}
160 except Exception as e
: # TODO refine
161 raise DbException(str(e
))
163 def replace(self
, table
, id, indata
, fail_on_empty
=True):
165 collection
= self
.db
[table
]
166 rows
= collection
.replace_one({"_id": id}, indata
)
167 if rows
.modified_count
== 0:
169 raise DbException("Not found entry with filter='{}'".format(filter), HTTPStatus
.NOT_FOUND
)
171 return {"replace": rows
.modified_count
}
172 except Exception as e
: # TODO refine
173 raise DbException(str(e
))