2020-12-23 12:25:17 +01:00
import json
2018-09-18 13:03:15 +02:00
import falcon
2020-12-18 21:42:06 +01:00
import psycopg2 . extras
2020-12-22 10:18:47 +01:00
from falcon_swagger_ui import register_swaggerui_app
2018-09-18 13:03:15 +02:00
2020-12-23 12:25:17 +01:00
from . config import DSPACE_STATISTICS_API_URL , VERSION
2019-11-27 11:31:04 +01:00
from . database import DatabaseManager
2020-12-20 15:28:56 +01:00
from . stats import get_downloads , get_views
2020-12-20 15:29:35 +01:00
from . util import set_statistics_scope , validate_post_parameters
2019-11-27 11:31:04 +01:00
2018-11-03 22:55:23 +01:00
2018-10-31 23:19:39 +01:00
class RootResource :
def on_get ( self , req , resp ) :
resp . status = falcon . HTTP_200
2019-11-27 11:30:06 +01:00
resp . content_type = " text/html "
2020-12-23 15:12:50 +01:00
docs_html = (
" <!DOCTYPE html> "
" <html lang= \" en-US \" > "
" <head> "
" <meta charset= \" UTF-8 \" > "
" <title>DSpace Statistics API</title> "
" </head> "
" <body> "
f " <h1>DSpace Statistics API { VERSION } </h1> "
f " <p>This site is running the <a href= \" https://github.com/ilri/dspace-statistics-api \" title= \" DSpace Statistics API project \" >DSpace Statistics API</a>. For more information see the project ' s README.md or the interactive <a href= \" { DSPACE_STATISTICS_API_URL + ' /swagger ' } \" >Swagger UI</a> built into this API.</p> "
" </body> "
" </html "
)
resp . body = docs_html
2018-10-31 23:19:39 +01:00
2018-11-03 22:55:23 +01:00
2020-12-22 10:30:09 +01:00
class StatusResource :
def on_get ( self , req , resp ) :
message = { " version " : VERSION }
resp . status = falcon . HTTP_200
resp . media = message
2020-12-22 10:18:47 +01:00
class OpenAPIJSONResource :
def on_get ( self , req , resp ) :
resp . status = falcon . HTTP_200
resp . content_type = " text/html "
with open ( " dspace_statistics_api/docs/openapi.json " , " r " ) as f :
2020-12-23 12:25:17 +01:00
# Load the openapi.json schema
data = json . load ( f )
# Swagger assumes your API is at the root of the current host unless
# you configure a "servers" block in the schema. The problem is that
# I want this to work in both development and production, so we need
# to make this configurable.
#
# If the DSPACE_STATISTICS_API_URL is configured then we will add a
# server entry to the openapi.json schema before sending it.
if DSPACE_STATISTICS_API_URL != " " :
data [ " servers " ] = [ { " url " : DSPACE_STATISTICS_API_URL } ]
resp . body = json . dumps ( data )
2020-12-22 10:18:47 +01:00
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
class AllStatisticsResource :
@falcon.before ( set_statistics_scope )
2018-09-24 15:07:26 +02:00
def on_get ( self , req , resp ) :
""" Handles GET requests """
# Return HTTPBadRequest if id parameter is not present and valid
2020-11-02 20:59:20 +01:00
limit = req . get_param_as_int ( " limit " , min_value = 1 , max_value = 100 ) or 100
2019-03-17 22:23:23 +01:00
page = req . get_param_as_int ( " page " , min_value = 0 ) or 0
2018-09-24 15:07:26 +02:00
offset = limit * page
2018-11-07 16:41:21 +01:00
with DatabaseManager ( ) as db :
db . set_session ( readonly = True )
2018-09-24 15:07:26 +02:00
2018-11-07 16:41:21 +01:00
with db . cursor ( ) as cursor :
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
# get total number of communities/collections/items so we can estimate the pages
cursor . execute ( f " SELECT COUNT(id) FROM { req . context . statistics_scope } " )
2018-11-07 16:41:21 +01:00
pages = round ( cursor . fetchone ( ) [ 0 ] / limit )
2018-09-24 15:07:26 +02:00
2020-03-02 10:06:27 +01:00
# get statistics and use limit and offset to page through results
2019-11-27 11:30:06 +01:00
cursor . execute (
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
f " SELECT id, views, downloads FROM { req . context . statistics_scope } ORDER BY id LIMIT %s OFFSET %s " ,
2020-03-02 10:16:05 +01:00
[ limit , offset ] ,
2019-11-27 11:30:06 +01:00
)
2018-09-24 15:07:26 +02:00
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
# create a list to hold dicts of stats
2018-11-07 16:41:21 +01:00
statistics = list ( )
2018-09-24 15:07:26 +02:00
2018-11-07 16:41:21 +01:00
# iterate over results and build statistics object
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
for result in cursor :
2019-11-27 11:30:06 +01:00
statistics . append (
{
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
" id " : str ( result [ " id " ] ) ,
" views " : result [ " views " ] ,
" downloads " : result [ " downloads " ] ,
2019-11-27 11:30:06 +01:00
}
)
2018-09-27 10:03:44 +02:00
2018-09-24 15:07:26 +02:00
message = {
2019-11-27 11:30:06 +01:00
" currentPage " : page ,
" totalPages " : pages ,
" limit " : limit ,
" statistics " : statistics ,
2018-09-24 15:07:26 +02:00
}
resp . media = message
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
@falcon.before ( set_statistics_scope )
@falcon.before ( validate_post_parameters )
dspace_statistics_api: Add support for date ranges to /items
You can now POST a JSON request to /items with a list of items and
a date range. This allows the possibility to get view and download
statistics for arbitrary items and arbitrary date ranges.
The JSON request should be in the following format:
{
"limit": 100,
"page": 0,
"dateFrom": "2020-01-01T00:00:00Z",
"dateTo": "2020-09-09T00:00:00Z",
"items": [
"f44cf173-2344-4eb2-8f00-ee55df32c76f",
"2324aa41-e9de-4a2b-bc36-16241464683e",
"8542f9da-9ce1-4614-abf4-f2e3fdb4b305",
"0fe573e7-042a-4240-a4d9-753b61233908"
]
}
The limit, page, and date parameters are all optional. By default
it will use a limit of 100, page 0, and [* TO *] Solr date range.
2020-09-25 11:21:11 +02:00
def on_post ( self , req , resp ) :
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
""" Handles POST requests.
Uses two ` before ` hooks to set the statistics " scope " and validate the
POST parameters . The " scope " is the type of statistics we want , which
will be items , communities , or collections , depending on the request .
"""
dspace_statistics_api: Add support for date ranges to /items
You can now POST a JSON request to /items with a list of items and
a date range. This allows the possibility to get view and download
statistics for arbitrary items and arbitrary date ranges.
The JSON request should be in the following format:
{
"limit": 100,
"page": 0,
"dateFrom": "2020-01-01T00:00:00Z",
"dateTo": "2020-09-09T00:00:00Z",
"items": [
"f44cf173-2344-4eb2-8f00-ee55df32c76f",
"2324aa41-e9de-4a2b-bc36-16241464683e",
"8542f9da-9ce1-4614-abf4-f2e3fdb4b305",
"0fe573e7-042a-4240-a4d9-753b61233908"
]
}
The limit, page, and date parameters are all optional. By default
it will use a limit of 100, page 0, and [* TO *] Solr date range.
2020-09-25 11:21:11 +02:00
# Build the Solr date string, ie: [* TO *]
2020-09-26 17:37:14 +02:00
if req . context . dateFrom and req . context . dateTo :
solr_date_string = f " [ { req . context . dateFrom } TO { req . context . dateTo } ] "
elif not req . context . dateFrom and req . context . dateTo :
solr_date_string = f " [* TO { req . context . dateTo } ] "
elif req . context . dateFrom and not req . context . dateTo :
solr_date_string = f " [ { req . context . dateFrom } TO *] "
dspace_statistics_api: Add support for date ranges to /items
You can now POST a JSON request to /items with a list of items and
a date range. This allows the possibility to get view and download
statistics for arbitrary items and arbitrary date ranges.
The JSON request should be in the following format:
{
"limit": 100,
"page": 0,
"dateFrom": "2020-01-01T00:00:00Z",
"dateTo": "2020-09-09T00:00:00Z",
"items": [
"f44cf173-2344-4eb2-8f00-ee55df32c76f",
"2324aa41-e9de-4a2b-bc36-16241464683e",
"8542f9da-9ce1-4614-abf4-f2e3fdb4b305",
"0fe573e7-042a-4240-a4d9-753b61233908"
]
}
The limit, page, and date parameters are all optional. By default
it will use a limit of 100, page 0, and [* TO *] Solr date range.
2020-09-25 11:21:11 +02:00
else :
solr_date_string = " [* TO *] "
# Helper variables to make working with pages/items/results easier and
# to make the code easier to understand
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
number_of_elements : int = len ( req . context . elements )
pages : int = int ( number_of_elements / req . context . limit )
first_element : int = req . context . page * req . context . limit
last_element : int = first_element + req . context . limit
dspace_statistics_api: Add support for date ranges to /items
You can now POST a JSON request to /items with a list of items and
a date range. This allows the possibility to get view and download
statistics for arbitrary items and arbitrary date ranges.
The JSON request should be in the following format:
{
"limit": 100,
"page": 0,
"dateFrom": "2020-01-01T00:00:00Z",
"dateTo": "2020-09-09T00:00:00Z",
"items": [
"f44cf173-2344-4eb2-8f00-ee55df32c76f",
"2324aa41-e9de-4a2b-bc36-16241464683e",
"8542f9da-9ce1-4614-abf4-f2e3fdb4b305",
"0fe573e7-042a-4240-a4d9-753b61233908"
]
}
The limit, page, and date parameters are all optional. By default
it will use a limit of 100, page 0, and [* TO *] Solr date range.
2020-09-25 11:21:11 +02:00
# Get a subset of the POSTed items based on our limit. Note that Python
# list slicing and indexing are both zero based, but the first and last
# items in a slice can be confusing. See this ASCII diagram:
#
# +---+---+---+---+---+---+
# | P | y | t | h | o | n |
# +---+---+---+---+---+---+
# Slice position: 0 1 2 3 4 5 6
# Index position: 0 1 2 3 4 5
#
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
# So if we have a list of items with 240 items:
dspace_statistics_api: Add support for date ranges to /items
You can now POST a JSON request to /items with a list of items and
a date range. This allows the possibility to get view and download
statistics for arbitrary items and arbitrary date ranges.
The JSON request should be in the following format:
{
"limit": 100,
"page": 0,
"dateFrom": "2020-01-01T00:00:00Z",
"dateTo": "2020-09-09T00:00:00Z",
"items": [
"f44cf173-2344-4eb2-8f00-ee55df32c76f",
"2324aa41-e9de-4a2b-bc36-16241464683e",
"8542f9da-9ce1-4614-abf4-f2e3fdb4b305",
"0fe573e7-042a-4240-a4d9-753b61233908"
]
}
The limit, page, and date parameters are all optional. By default
it will use a limit of 100, page 0, and [* TO *] Solr date range.
2020-09-25 11:21:11 +02:00
#
2020-09-26 17:37:14 +02:00
# 1st set: items[0:100] would give items at indexes 0 to 99
# 2nd set: items[100:200] would give items at indexes 100 to 199
# 3rd set: items[200:300] would give items at indexes 200 to 239
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
elements_subset : list = req . context . elements [ first_element : last_element ]
dspace_statistics_api: Add support for date ranges to /items
You can now POST a JSON request to /items with a list of items and
a date range. This allows the possibility to get view and download
statistics for arbitrary items and arbitrary date ranges.
The JSON request should be in the following format:
{
"limit": 100,
"page": 0,
"dateFrom": "2020-01-01T00:00:00Z",
"dateTo": "2020-09-09T00:00:00Z",
"items": [
"f44cf173-2344-4eb2-8f00-ee55df32c76f",
"2324aa41-e9de-4a2b-bc36-16241464683e",
"8542f9da-9ce1-4614-abf4-f2e3fdb4b305",
"0fe573e7-042a-4240-a4d9-753b61233908"
]
}
The limit, page, and date parameters are all optional. By default
it will use a limit of 100, page 0, and [* TO *] Solr date range.
2020-09-25 11:21:11 +02:00
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
views : dict = get_views (
solr_date_string , elements_subset , req . context . views_facet_field
)
downloads : dict = get_downloads (
solr_date_string , elements_subset , req . context . downloads_facet_field
)
dspace_statistics_api: Add support for date ranges to /items
You can now POST a JSON request to /items with a list of items and
a date range. This allows the possibility to get view and download
statistics for arbitrary items and arbitrary date ranges.
The JSON request should be in the following format:
{
"limit": 100,
"page": 0,
"dateFrom": "2020-01-01T00:00:00Z",
"dateTo": "2020-09-09T00:00:00Z",
"items": [
"f44cf173-2344-4eb2-8f00-ee55df32c76f",
"2324aa41-e9de-4a2b-bc36-16241464683e",
"8542f9da-9ce1-4614-abf4-f2e3fdb4b305",
"0fe573e7-042a-4240-a4d9-753b61233908"
]
}
The limit, page, and date parameters are all optional. By default
it will use a limit of 100, page 0, and [* TO *] Solr date range.
2020-09-25 11:21:11 +02:00
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
# create a list to hold dicts of stats
dspace_statistics_api: Add support for date ranges to /items
You can now POST a JSON request to /items with a list of items and
a date range. This allows the possibility to get view and download
statistics for arbitrary items and arbitrary date ranges.
The JSON request should be in the following format:
{
"limit": 100,
"page": 0,
"dateFrom": "2020-01-01T00:00:00Z",
"dateTo": "2020-09-09T00:00:00Z",
"items": [
"f44cf173-2344-4eb2-8f00-ee55df32c76f",
"2324aa41-e9de-4a2b-bc36-16241464683e",
"8542f9da-9ce1-4614-abf4-f2e3fdb4b305",
"0fe573e7-042a-4240-a4d9-753b61233908"
]
}
The limit, page, and date parameters are all optional. By default
it will use a limit of 100, page 0, and [* TO *] Solr date range.
2020-09-25 11:21:11 +02:00
statistics = list ( )
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
# iterate over views dict to extract views and use the element id as an
dspace_statistics_api: Add support for date ranges to /items
You can now POST a JSON request to /items with a list of items and
a date range. This allows the possibility to get view and download
statistics for arbitrary items and arbitrary date ranges.
The JSON request should be in the following format:
{
"limit": 100,
"page": 0,
"dateFrom": "2020-01-01T00:00:00Z",
"dateTo": "2020-09-09T00:00:00Z",
"items": [
"f44cf173-2344-4eb2-8f00-ee55df32c76f",
"2324aa41-e9de-4a2b-bc36-16241464683e",
"8542f9da-9ce1-4614-abf4-f2e3fdb4b305",
"0fe573e7-042a-4240-a4d9-753b61233908"
]
}
The limit, page, and date parameters are all optional. By default
it will use a limit of 100, page 0, and [* TO *] Solr date range.
2020-09-25 11:21:11 +02:00
# index to the downloads dict to extract downloads.
for k , v in views . items ( ) :
statistics . append ( { " id " : k , " views " : v , " downloads " : downloads [ k ] } )
message = {
2020-09-26 17:37:14 +02:00
" currentPage " : req . context . page ,
dspace_statistics_api: Add support for date ranges to /items
You can now POST a JSON request to /items with a list of items and
a date range. This allows the possibility to get view and download
statistics for arbitrary items and arbitrary date ranges.
The JSON request should be in the following format:
{
"limit": 100,
"page": 0,
"dateFrom": "2020-01-01T00:00:00Z",
"dateTo": "2020-09-09T00:00:00Z",
"items": [
"f44cf173-2344-4eb2-8f00-ee55df32c76f",
"2324aa41-e9de-4a2b-bc36-16241464683e",
"8542f9da-9ce1-4614-abf4-f2e3fdb4b305",
"0fe573e7-042a-4240-a4d9-753b61233908"
]
}
The limit, page, and date parameters are all optional. By default
it will use a limit of 100, page 0, and [* TO *] Solr date range.
2020-09-25 11:21:11 +02:00
" totalPages " : pages ,
2020-09-26 17:37:14 +02:00
" limit " : req . context . limit ,
dspace_statistics_api: Add support for date ranges to /items
You can now POST a JSON request to /items with a list of items and
a date range. This allows the possibility to get view and download
statistics for arbitrary items and arbitrary date ranges.
The JSON request should be in the following format:
{
"limit": 100,
"page": 0,
"dateFrom": "2020-01-01T00:00:00Z",
"dateTo": "2020-09-09T00:00:00Z",
"items": [
"f44cf173-2344-4eb2-8f00-ee55df32c76f",
"2324aa41-e9de-4a2b-bc36-16241464683e",
"8542f9da-9ce1-4614-abf4-f2e3fdb4b305",
"0fe573e7-042a-4240-a4d9-753b61233908"
]
}
The limit, page, and date parameters are all optional. By default
it will use a limit of 100, page 0, and [* TO *] Solr date range.
2020-09-25 11:21:11 +02:00
" statistics " : statistics ,
}
resp . status = falcon . HTTP_200
resp . media = message
2018-11-03 22:55:23 +01:00
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
class SingleStatisticsResource :
@falcon.before ( set_statistics_scope )
def on_get ( self , req , resp , id_ ) :
2018-09-18 13:03:15 +02:00
""" Handles GET requests """
2020-03-02 10:06:27 +01:00
# Adapt Python’ s uuid.UUID type to PostgreSQL’ s uuid
# See: https://www.psycopg.org/docs/extras.html
psycopg2 . extras . register_uuid ( )
2018-11-07 16:41:21 +01:00
with DatabaseManager ( ) as db :
db . set_session ( readonly = True )
with db . cursor ( ) as cursor :
cursor = db . cursor ( )
2019-11-27 11:30:06 +01:00
cursor . execute (
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
f " SELECT views, downloads FROM { req . context . database } WHERE id=%s " ,
[ str ( id_ ) ] ,
2019-11-27 11:30:06 +01:00
)
2018-11-07 16:41:21 +01:00
if cursor . rowcount == 0 :
raise falcon . HTTPNotFound (
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
title = f " { req . context . statistics_scope } not found " ,
description = f ' The { req . context . statistics_scope } with id " { str ( id_ ) } " was not found. ' ,
2018-11-07 16:41:21 +01:00
)
else :
results = cursor . fetchone ( )
statistics = {
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
" id " : str ( id_ ) ,
2019-11-27 11:30:06 +01:00
" views " : results [ " views " ] ,
" downloads " : results [ " downloads " ] ,
2018-11-07 16:41:21 +01:00
}
resp . media = statistics
2018-09-18 13:03:15 +02:00
2018-11-03 22:55:23 +01:00
2018-10-26 18:21:27 +02:00
api = application = falcon . API ( )
2019-11-27 11:30:06 +01:00
api . add_route ( " / " , RootResource ( ) )
2020-12-22 10:30:09 +01:00
api . add_route ( " /status " , StatusResource ( ) )
Add communities and collections support to API
The basic logic is similar to items, where you can request single
item statistics with a UUID, all item statistics, and item statis-
tics for a list of items (optionally with a date range). Most of
the item code was re-purposed to work on "elements", which can be
items, communities, or collections depending on the request, with
the use of Falcon's `before` hooks to set the statistics scope so
we know how to behave for the current request.
Other than the minor difference in facet fields, another issue I
had with communities and collections is that the owningComm and
owningColl fields are multi-valued (unlike items' id field). This
means that, when you facet the results of your query, Solr returns
ids that seem unrelated, but are actually present in the field, so
I had to make sure I checked all returned ids to see if they were
in the user's POSTed elements list.
TODO:
- Add tests
- Revise docstrings
- Refactor items.py as it is now generic
2020-12-20 15:14:46 +01:00
# Item routes
api . add_route ( " /items " , AllStatisticsResource ( ) )
api . add_route ( " /item/ { id_:uuid} " , SingleStatisticsResource ( ) )
# Community routes
api . add_route ( " /communities " , AllStatisticsResource ( ) )
api . add_route ( " /community/ { id_:uuid} " , SingleStatisticsResource ( ) )
# Collection routes
api . add_route ( " /collections " , AllStatisticsResource ( ) )
api . add_route ( " /collection/ { id_:uuid} " , SingleStatisticsResource ( ) )
2018-09-23 10:33:26 +02:00
2020-12-23 12:25:17 +01:00
# Route to the Swagger UI OpenAPI schema
api . add_route ( " /docs/openapi.json " , OpenAPIJSONResource ( ) )
# Path to host the Swagger UI. Keep in mind that Falcon will add a route for
# this automatically when we register Swagger and the path will be relative
# to the Falcon app like all other routes, not the absolute root.
SWAGGERUI_PATH = " /swagger "
# The *absolute* path to the OpenJSON schema. This must be absolute because
# it will be requested by the client and must resolve absolutely. Note: the
# name of this variable is misleading because it is actually the schema URL
# but we pass it into the register_swaggerui_app() function as the api_url
# parameter.
SWAGGERUI_API_URL = f " { DSPACE_STATISTICS_API_URL } /docs/openapi.json "
2020-12-22 10:18:47 +01:00
register_swaggerui_app (
api ,
2020-12-23 12:25:17 +01:00
SWAGGERUI_PATH ,
SWAGGERUI_API_URL ,
2020-12-22 10:18:47 +01:00
config = {
" supportedSubmitMethods " : [ " get " , " post " ] ,
} ,
2020-12-23 12:25:17 +01:00
uri_prefix = DSPACE_STATISTICS_API_URL ,
2020-12-22 10:18:47 +01:00
)
2018-09-23 10:33:26 +02:00
# vim: set sw=4 ts=4 expandtab: