Ticket 749: Handling non-unique identifiers in /what/source jenkins-baltrad-db-422
authorMats Vernersson <mats.vernersson@smhi.se>
Thu, 28 Jun 2018 11:44:08 +0000 (13:44 +0200)
committerMats Vernersson <mats.vernersson@smhi.se>
Thu, 28 Jun 2018 11:44:08 +0000 (13:44 +0200)
A new method for matching the correct source for a source-string has been implemented in the get_source_id-function of backend.py. With the new method, all matching key-value pairs of the database are collected and evaluated. If there are multiple source ids that have any matching key-value pair, the one that has the highest number of matches is selected.

server/itest/sqla/backend_test.py
server/src/baltrad/bdbserver/sqla/backend.py

index 05bb260..9a152e2 100644 (file)
@@ -44,7 +44,9 @@ class TestSqlAlchemyBackendItest(object):
 
     sources = [
         Source("eesur", values={"NOD": "eesur", "PLC": "Syrgavere"}),
-        Source("eehar", values={"NOD": "eehar", "PLC": "Harku"})
+        Source("eehar", values={"NOD": "eehar", "PLC": "Harku"}),
+        Source("dkaal", values={"WMO": "00000", "NOD": "dkaal", "PLC": "Aalborg"}),
+        Source("sebaa", values={"WMO": "00000", "NOD": "sebaa", "PLC": "Balsta"})
     ]
 
     source_ids = []
@@ -87,6 +89,12 @@ class TestSqlAlchemyBackendItest(object):
         source = {"NOD": "eesur"}
         with self.backend.get_connection() as conn:
             eq_(self.source_ids[0], get_source_id(conn, source))
+            
+    @attr("dbtest")
+    def test_get_source_id_multiple_wmo_matches(self):
+        source = {"WMO": "00000", "NOD": "sebaa"}
+        with self.backend.get_connection() as conn:
+            eq_(self.source_ids[3], get_source_id(conn, source))
     
     @attr("dbtest")
     def test_store_file(self):
index 6aed5c4..340968f 100644 (file)
@@ -671,7 +671,6 @@ def _has_file_by_hash_and_source(conn, hash, source_id):
         )
     ).scalar()
 
-
 def get_source_id(conn, source):
     where = sql.literal(False)
     keys = source.keys()
@@ -679,7 +678,7 @@ def get_source_id(conn, source):
     if "ORG" in keys:
         if "WMO" in keys or "NOD" in keys or "RAD" in keys or "PLC" in keys:
             ignoreORG=True
-
     for key, value in source.items():
         if ignoreORG and key == "ORG":
             continue
@@ -690,14 +689,42 @@ def get_source_id(conn, source):
                 schema.source_kvs.c.value==value
             )
         )
-
     qry = sql.select(
-        [schema.source_kvs.c.source_id],
+        [schema.source_kvs.c.source_id, schema.source_kvs.c.key, schema.source_kvs.c.value],
         where,
         distinct=True
     )
-
-    return conn.execute(qry).scalar()
+     
+    result = conn.execute(qry)
+     
+    source_id_matches = {}
+    max_no_of_matches = 0
+    best_match_id = None
+    multiple_matches = False
+    for row in result:
+        source_id = row[schema.source_kvs.c.source_id]
+        if not source_id in source_id_matches:
+            source_id_matches[source_id] = 0
+        row_key = row[schema.source_kvs.c.key]
+        row_value = row[schema.source_kvs.c.value]
+        for key, value in source.items():
+            if ignoreORG and key == "ORG":
+                continue
+            elif key == row_key and value == row_value:
+                source_id_matches[source_id] += 1
+                if source_id_matches[source_id] > max_no_of_matches:
+                    max_no_of_matches = source_id_matches[source_id]
+                    best_match_id = source_id
+                    multiple_matches = False
+                elif source_id_matches[source_id] == max_no_of_matches:
+                    multiple_matches = True
+     
+    if multiple_matches:
+      logger.debug("Could not determine source due to multiple equally matching sources found for %s." % (str(source)))
+      best_match_id = None
+    return best_match_id
 
 def get_source_id_by_name(conn, name):
     qry = sql.select(