Skip to content

Commit 50048d5

Browse files
committed
feat: add merge_dict, remove_paths & json_type to update_json_field
1 parent 1a63bd6 commit 50048d5

File tree

4 files changed

+55
-24
lines changed

4 files changed

+55
-24
lines changed

README.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,25 +77,31 @@ Generate sql and execute
7777
LIMIT 10
7878
```
7979

80-
### **upsert_json_field**
80+
### **update_json_field**
8181
```python
82-
await AccountMgr.upsert_json_field(
82+
await AccountMgr.update_json_field(
8383
json_field="extend",
84+
wheres=Q(id=8),
85+
merge_dict={
86+
"updated_at": "2022-10-30 21:34:15",
87+
"info": {
88+
"online_sec": 636,
89+
}
90+
},
8491
path_value_dict={
8592
"$.last_login": {
8693
"ipv4": "209.182.101.161",
87-
"start_datetime": "2022-10-16 11:11:05",
88-
"online_sec": 4209,
8994
},
9095
"$.uuid": "fd04f7f2-24fc-4a73-a1d7-b6e99a464c5f",
9196
},
92-
wheres=Q(id=8),
97+
remove_paths=["$.deprecated"],
98+
json_type=dict,
9399
)
94100
```
95101
Generate sql and execute
96102
```sql
97-
UPDATE account
98-
SET extend = JSON_SET(COALESCE(extend, '{}'), '$.last_login', CAST('{"ipv4": "209.182.101.161", "start_datetime": "2022-10-16 11:11:05", "online_sec": 4209}' AS JSON), '$.uuid', 'fd04f7f2-24fc-4a73-a1d7-b6e99a464c5f')
103+
UPDATE account SET extend =
104+
JSON_MERGE_PATCH(JSON_SET(JSON_REMOVE(COALESCE(extend, '{}'), '$.deprecated'), '$.last_login',CAST('{"ipv4": "209.182.101.161"}' AS JSON), '$.uuid','fd04f7f2-24fc-4a73-a1d7-b6e99a464c5f'), '{"updated_at": "2022-10-30 21:34:15", "info": {"online_sec": 636}}')
99105
WHERE `id`=8
100106
```
101107

examples/service/routers/account.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,17 +116,23 @@ async def update_last_login_view(
116116
aid: int = Query(...),
117117
):
118118
faker = Faker()
119-
row_cnt = await AccountMgr.upsert_json_field(
119+
row_cnt = await AccountMgr.update_json_field(
120120
json_field="extend",
121+
wheres=Q(id=aid),
122+
merge_dict={
123+
"updated_at": str(faker.past_datetime()),
124+
"info": {
125+
"online_sec": faker.random_int(),
126+
}
127+
},
121128
path_value_dict={
122129
"$.last_login": {
123130
"ipv4": faker.ipv4(),
124-
"start_datetime": str(faker.past_datetime()),
125-
"online_sec": faker.random_int(),
126131
},
127132
"$.uuid": faker.uuid4(),
128133
},
129-
wheres=Q(id=aid),
134+
remove_paths=["$.deprecated"],
135+
json_type=dict,
130136
)
131137
return {"row_cnt": row_cnt}
132138

fastapi_esql/orm/base_manager.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,17 +83,23 @@ async def select_custom_fields(
8383
return await CursorHandler.fetch_dicts(sql, conn, logger)
8484

8585
@classmethod
86-
async def upsert_json_field(
86+
async def update_json_field(
8787
cls,
8888
json_field: str,
89-
path_value_dict: Dict[str, Any],
9089
wheres: Union[str, Q, Dict[str, Any], List[Q]],
90+
merge_dict: Optional[Dict[str, Any]] = None,
91+
path_value_dict: Optional[Dict[str, Any]] = None,
92+
remove_paths: Optional[List[str]] = None,
93+
json_type: type = dict,
9194
):
92-
sql = SQLizer.upsert_json_field(
95+
sql = SQLizer.update_json_field(
9396
cls.table,
9497
json_field,
95-
path_value_dict,
9698
wheres,
99+
merge_dict,
100+
path_value_dict,
101+
remove_paths,
102+
json_type,
97103
cls.model,
98104
)
99105
return await CursorHandler.sum_row_cnt(sql, cls.rw_conn, logger)

fastapi_esql/utils/sqlizer.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -121,25 +121,38 @@ def select_custom_fields(
121121
return sql
122122

123123
@classmethod
124-
def upsert_json_field(
124+
def update_json_field(
125125
cls,
126126
table: str,
127127
json_field: str,
128-
path_value_dict: Dict[str, Any],
129128
wheres: Union[str, Q, Dict[str, Any], List[Q]],
129+
merge_dict: Optional[Dict[str, Any]] = None,
130+
path_value_dict: Optional[Dict[str, Any]] = None,
131+
remove_paths: Optional[List[str]] = None,
132+
json_type: type = dict,
130133
model: Optional[Model] = None,
131134
) -> Optional[str]:
132-
if not all([table, json_field, path_value_dict, wheres]):
135+
if not all([table, json_field, wheres]):
136+
raise WrongParamsError("Please check your params")
137+
if not any([merge_dict, path_value_dict, remove_paths]):
133138
raise WrongParamsError("Please check your params")
134139

135-
params = []
136-
for (path, value) in path_value_dict.items():
137-
params.append(f"'{path}'")
138-
params.append(cls._sqlize_value(value, to_json=True))
140+
json_obj = f"COALESCE({json_field}, '{json_type()}')"
141+
if remove_paths:
142+
rps = ", ".join(f"'{p}'" for p in remove_paths)
143+
json_obj = f"JSON_REMOVE({json_obj}, {rps})"
144+
if path_value_dict:
145+
pvs = [
146+
f"'{path}',{cls._sqlize_value(value, to_json=True)}"
147+
for (path, value) in path_value_dict.items()
148+
]
149+
json_obj = f"JSON_SET({json_obj}, {', '.join(pvs)})"
150+
if merge_dict:
151+
json_obj = f"JSON_MERGE_PATCH({json_obj}, {cls._sqlize_value(merge_dict)})"
139152

140153
sql = f"""
141-
UPDATE {table}
142-
SET {json_field} = JSON_SET(COALESCE({json_field}, '{{}}'), {", ".join(params)})
154+
UPDATE {table} SET {json_field} =
155+
{json_obj}
143156
WHERE {cls.resolve_wheres(wheres, model)}"""
144157
logger.debug(sql)
145158
return sql

0 commit comments

Comments
 (0)