-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Distinct Filter for Python ICAT Backend #161
Conversation
- This changes the output of the data to a list of values, rather than the traditional list of dictionaries, containing attribute name and its value
- The primary used for this operation will be to add WHERE filters when a distinct filter is in a request, so distinct filters can accomodate multiple fields
…from helper side - This requires the addition of creating WHERE filters within a distinct filter to deal with multiple fields within a single distinct filter
- Inside a PythonICATDistinctFieldFilter, a where filter is created for each field in the request. These are then searched for in execute_icat_query() and the data is compiled to only include data from those fields
- Combine some of the logic with the existing logic where `return_json_formattable` is True - this will ensure that datetimes are converted to an appropriate format when using distinct filters - This commit also adds checking of the query's conditions to only select attribute names of those which are "!= null" as set by the distinct filter
- Turned the two functions into a class, since these are related operations - This change has been made so I can add another function to this class later on
…pping WHERE filter - This change means that if there's a distinct filter of an attribute, and a WHERE filter specifying a condition of the same attribute, the distinct filter will act as intended (where before the data of that attribute wasn't added to the response)
… using distinct filter
- This change fixes a bug where if a value used for a WHERE filter with an IN operation had only a single element in a list, it would cause a JPQL error. This happened because the list was converted into a tuple (to satisfy JPQL formatting of array based data). With single element tuples, Python adds a trailing comma, something which is invalid in JPQL. The value is now converted into a string, with the square brackets being replaced with normal brackets before being sent off to JPQL. - Also added type checking on the value if an IN operation is used to ensure the value is a list
…-distinct-filter-#141
Fixed merge conflict for this PR. |
In my description regarding this PR, I questioned whether the |
Changed base branch due to merging limit/skip filters into the where filter branch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I try to add a where filter to a field which has been specified to be distinct, I get "No results found". This would be required to filter the Diamond Proposal table, which uses distinct filters to get investigation names & titles and you can filter on names and titles as well.
e.g. the following request does not work:
http://localhost:500-/investigations?distinct=["name", "title"]&where={"title": {"like": "dog"}}
@louise-davies:
You'd have thought the second one is 'like' the piece of data I'm after (i.e. As for the overarching feature required for Diamond, I do believe this works:
As described above, this seems to be a LIKE operator issue. Right now, I'm a little bit stumped about what to do (Python ICAT deals with the LIKE operator itself, I just parse the value from the request), but hopefully I can think of something for next week. |
@MRichards99 - this might require adding |
- This should allow these types of searches to provide more accurate results, where previously none could be found
Just made the change and it seems to work! Have a go and see what you think :) |
This PR closes #141.
This adds functionality for the distinct filter. Like the database backend, either a single field can be used, or a list of fields can be entered to be "distinct". Multiple distinct filters can be used in a single request without them overwriting each other, which I didn't expect I could do at the start of looking at this issue, so that's good :)
Since Python ICAT only really supports a single field to be distinct (through the use of
setAttribute()
and setting DISTINCT usingsetAggregate()
), I had to get a little creative. I usedsetAggregate()
to add the DISTINCT part to the JPQL query, but to set which fields are distinct, I build WHERE filters within a distinct filter (one where filter per field). The WHERE filters are set to look for anything that isn't null so it'll pick up the data. The data returned from the JPQL query has all the attributes of an entity so the fields and data specified in the distinct filter are picked out and returned in the response. Having done identical requests on both backends, this seems to return exactly the same data, in the same format.Within
common/icat/helpers.py
, I've movedconstruct_icat_query()
andexecute_icat_query()
into its own class as it seems to make sense to do so. I made this change largely because I added a function calledcheck_attribute_name_for_distinct()
which is only used inexecute_icat_query()
so it seemed to make sense to move all 3 functions into their own class. Thinking about it now, I wonder if theicat_query
class should go in its own file, any thoughts?There's also a bug fix for the WHERE filter - this is explained within the commit 2aea37c.