ckanext-googleanalytics/ckanext/googleanalytics/dbutil.py

131 lines
3.8 KiB
Python

from sqlalchemy import Table, Column, Integer, String, MetaData
from sqlalchemy.sql import select, text
from sqlalchemy import func
import ckan.model as model
cached_tables = {}
def init_tables():
metadata = MetaData()
Table(
"package_stats",
metadata,
Column("package_id", String(60), primary_key=True),
Column("visits_recently", Integer),
Column("visits_ever", Integer),
)
Table(
"resource_stats",
metadata,
Column("resource_id", String(60), primary_key=True),
Column("visits_recently", Integer),
Column("visits_ever", Integer),
)
metadata.create_all(model.meta.engine)
def get_table(name):
if name not in cached_tables:
meta = MetaData()
meta.reflect(bind=model.meta.engine)
table = meta.tables[name]
cached_tables[name] = table
return cached_tables[name]
def _update_visits(table_name, item_id, recently, ever):
stats = get_table(table_name)
id_col_name = "%s_id" % table_name[: -len("_stats")]
id_col = getattr(stats.c, id_col_name)
s = select([func.count(id_col)], id_col == item_id)
connection = model.Session.connection()
count = connection.execute(s).fetchone()
if count and count[0]:
connection.execute(
stats.update()
.where(id_col == item_id)
.values(visits_recently=recently, visits_ever=ever)
)
else:
values = {
id_col_name: item_id,
"visits_recently": recently,
"visits_ever": ever,
}
connection.execute(stats.insert().values(**values))
def update_resource_visits(resource_id, recently, ever):
return _update_visits("resource_stats", resource_id, recently, ever)
def update_package_visits(package_id, recently, ever):
return _update_visits("package_stats", package_id, recently, ever)
def get_resource_visits_for_url(url):
connection = model.Session.connection()
count = connection.execute(
text(
"""SELECT visits_ever FROM resource_stats, resource
WHERE resource_id = resource.id
AND resource.url = :url"""
),
url=url,
).fetchone()
return count and count[0] or ""
""" get_top_packages is broken, and needs to be rewritten to work with
CKAN 2.*. This is because ckan.authz has been removed in CKAN 2.*
See commit ffa86c010d5d25fa1881c6b915e48f3b44657612
"""
def get_top_packages(limit=20):
items = []
# caveat emptor: the query below will not filter out private
# or deleted datasets (TODO)
q = model.Session.query(model.Package)
connection = model.Session.connection()
package_stats = get_table("package_stats")
s = select(
[
package_stats.c.package_id,
package_stats.c.visits_recently,
package_stats.c.visits_ever,
]
).order_by(package_stats.c.visits_recently.desc())
res = connection.execute(s).fetchmany(limit)
for package_id, recent, ever in res:
item = q.filter(text("package.id = '%s'" % package_id))
if not item.count():
continue
items.append((item.first(), recent, ever))
return items
def get_top_resources(limit=20):
items = []
connection = model.Session.connection()
resource_stats = get_table("resource_stats")
s = select(
[
resource_stats.c.resource_id,
resource_stats.c.visits_recently,
resource_stats.c.visits_ever,
]
).order_by(resource_stats.c.visits_recently.desc())
res = connection.execute(s).fetchmany(limit)
for resource_id, recent, ever in res:
item = model.Session.query(model.Resource).filter(
"resource.id = '%s'" % resource_id
)
if not item.count():
continue
items.append((item.first(), recent, ever))
return items