Kaynağa Gözat

Make `/people` fast(er)

Maarten van den Berg 3 yıl önce
ebeveyn
işleme
17ec2d51ac
1 değiştirilmiş dosya ile 34 ekleme ve 3 silme
  1. 34 3
      piket_server/__init__.py

+ 34 - 3
piket_server/__init__.py

@@ -4,6 +4,7 @@ Piket server, handles events generated by the client.
4 4
 
5 5
 import datetime
6 6
 import os
7
+from collections import defaultdict
7 8
 
8 9
 from sqlalchemy.exc import SQLAlchemyError
9 10
 from sqlalchemy import func
@@ -49,7 +50,7 @@ class Person(db.Model):
49 50
                 .filter_by(consumption_type=ct)
50 51
                 .filter_by(reversed=False)
51 52
                 .count()
52
-                for ct in ConsumptionType.query.all()
53
+                for ct in ConsumptionType.query.filter_by(active=True).all()
53 54
             },
54 55
         }
55 56
 
@@ -253,13 +254,43 @@ def status() -> None:
253 254
 @app.route("/people", methods=["GET"])
254 255
 def get_people():
255 256
     """ Return a list of currently known people. """
256
-    people = Person.query.order_by(Person.name).all()
257 257
     q = Person.query.order_by(Person.name)
258 258
     if request.args.get("active"):
259 259
         active_status = request.args.get("active", type=int)
260 260
         q = q.filter_by(active=active_status)
261 261
     people = q.all()
262
-    result = [person.as_dict for person in people]
262
+
263
+    engine = db.get_engine()
264
+    query = '''
265
+        SELECT
266
+            consumptions.person_id,
267
+            consumptions.consumption_type_id,
268
+            COUNT(*)
269
+        FROM consumptions
270
+        JOIN consumption_types
271
+            ON consumptions.consumption_type_id = consumption_types.consumption_type_id
272
+        WHERE
273
+            consumptions.settlement_id IS NULL
274
+            AND consumptions.reversed = 0
275
+        GROUP BY consumptions.person_id, consumptions.consumption_type_id;
276
+    '''
277
+    raw_counts = engine.execute(query)
278
+
279
+    counts: 'Dict[int, Dict[str, int]]' = defaultdict(dict)
280
+    for person_id, consumption_type_id, count in raw_counts:
281
+        counts[person_id][str(consumption_type_id)] = count
282
+
283
+    result = [
284
+        {
285
+            "name": person.name,
286
+            "active": person.active,
287
+            "person_id": person.person_id,
288
+            "consumptions": counts[person.person_id]
289
+        }
290
+        for person in people
291
+    ]
292
+
293
+    # result = [person.as_dict for person in people]
263 294
     return jsonify(people=result)
264 295
 
265 296