Custom filter with nativeQuery - doctrine-orm

I want to perform a custom filter to retrieve an area inside a boundingBox via a custom filter
basic query will be like this:
SELECT * FROM public.area
where coord
# ST_MakeEnvelope (
-71, 48,
-72, 49)
In filterProperty method we have access only to the queryBuilder (due to the logic of apiplatform)
that we look something like this:
$queryBuilder
->andWhere('o.coord # ST_MakeEnvelope(:min_x, :min_y, :max_x, :max_y))')
but doctrine parser throw an error because of the unknown operator (see How do I use custom-operators in Doctrine DQL?)
so my only option is to perform a nativeQuery but with the logic of ApiPlatform I don't know how to achieve that, im not sure if it's even possible without breaking the logic of ApiPlatform filter
package used for postGIS is https://github.com/jsor/doctrine-postgis

Related

Django Rest Framework serializers.DictField constraint on possible keys

I have a REST API output that looks like this:
{
"something": "xyz"
"something_dict" {
"a": 10,
"b": 20,
"c": 30
}
}
I'm trying to create a serializer for that (mostly for automatic documentation generation purposes, but I believe that doesn't really matter), and for the something_dict field I thought it could be a good idea to use serializers.DictField.
The problem is, the keys that can show up in the dictionary are limited to a certain set (values of an enum type), but I can't seem to find a good way to define it.
Something like serializers.DictField(key=serializers.ChoiceField(choices=[enum.value for enum in Enum])) would be great but that's obviously not available.
The only reasonable way to specify this is to use a nested serializer:
class SomethingDict(serializers.Serializer):
a = serializers.IntField(required=False)
b = serializers.IntField(required=False)
c = serializers.IntField(required=False)
But that's slightly inconvenient as the set of available keys is potentially dynamic (values of an enum, as mentioned previously).
The question is then:
Is it possible to specify possible values for serializer.DictField keys or is there any way around it to make it dynamic? (I'd like to avoid defining the class in dynamic way, if possible)
Django Rest Framework provides a DictField serializer field that can be used to handle dictionaries in your API.
You can add a constraint on the possible keys of the dictionary by subclassing DictField and overriding the to_internal_value() method to perform the necessary validation.
Have a look at this example,
from rest_framework import serializers
class ConstrainedDictField(serializers.DictField):
def to_internal_value(self, data):
# Perform validation on the keys of the dictionary here
if set(data.keys()) != {"key1", "key2"}:
raise serializers.ValidationError("Invalid keys for dictionary.")
return super().to_internal_value(data)
You can then use the ConstrainedDictField in your serializer like this:
class MySerializer(serializers.Serializer):
my_dict = ConstrainedDictField()
It will only accept dictionary with key key1 and key2.

Django annotate count in JSONField with Postgres

Using Django I have a field which is of type JSONField. I am wanting to get a distinct count on a nested key/value in the json. With a normal field you can just do soemthing like the following
model.objects.values('field_name')\
.annotate(total=Count('field_name')).order_by('-total')
This does not work for a JSONField.
Example Model
class Pet(models.Model):
data = JSONField()
Example of data
{
'name':'sparky',
'animal':'dog',
'diet':{
'breakfast':'biscuits',
'dinner':'meat',
}
}
Trying
Pet.objects.values('data__diet__dinner')\
.annotate(total=Count('data__diet__dinner')).order_by('-total')
Exception of
TypeError: unhashable type: 'list'
What is the correct way to execute this?
You can use jsonb_extract_path_text via a Func object as an alternative to the field transform:
Pet.annotate(dinner=Func(
F('data'), Value('diet'), Value('dinner'),
function='jsonb_extract_path_text')) \
.values('dinner') \
.annotate(total=Count('dinner'))
The reason why the field transform data__diet__dinner fails is an error within Django when you go deeper than just one level into the json structure and use GROUP BY in the SQL. The first level (name, animal, diet) should work fine.
The reason seems to be that for nested transforms, Django changes the SQL syntax used, switching from a single value to a list to specify the path into the json structure.
This is the syntax used for non-nested json transforms (= first level):
"appname_pet"."data" -> 'diet'
And this is the syntax used for nested transforms (deeper than first level):
"appname_pet"."data" #> ARRAY['diet', 'dinner']
While constructing the query, Django chokes on that list while working out the required GROUP BY clauses. This does not seem to be an inevitable restriction; the support for transforms is quite new, and this is possibly one of the kinks that haven't been worked out yet. So if you open a Django ticket, this might just work a few versions down the line.

Django Postgres Case Insensitive Textfield and citext

for my Django app i use PostgreSQL (9.3) and i want to use case insensitive text in my database. For this Popstgres has a 'new' extension named 'citext'.
As i understand it, django can't use this extension out of the box, so i have made an custom field:
class RsCharField(models.CharField):
...
def db_type(self, connection):
return 'citext'
I use a CharField as baseclass, because i still want all the django perks of being able to set a maximum length and the validators that come with that.
The database is created correctly and i end up with citext-tables:
description | citext | not null
But when i do a query, django translates te query to:
SELECT * FROM .... WHERE mytable.description::text LIKE 'TEST%'
which still is case sensitive. When i do a manual select and drop the ::text it works case-insensitive.
Question: What am i doing wrong, and how can i make my CharFields behave like case-insensitive fields in django when doing queries?
note: most importantly i want my indexes to behave like case insensitive indexes.
use the classes provided in django.contrib.postgres.fields.citext
https://docs.djangoproject.com/pt-br/1.11/_modules/django/contrib/postgres/fields/citext/

Partial text search with postgreql & django

Tried to implement partial text search with postgresql and django,used the following query
Entry.objects.filter(headline__contains="search text")
This returns records having exact match,ie suppose checking for a match against the record "welcome to the new world" with query __contains="welcome world" , returns zero records
How can i implement this partial text search with postgresql-8.4 and django?
If you want this exact partial search you can use the startswitch field lookup method: Entry.objects.filter(headline__startswith="search text"). See more info at https://docs.djangoproject.com/en/dev/ref/models/querysets/#startswith.
This method creates a LIKE query ("SELECT ... WHERE headline LIKE 'search text%'") so if you're looking for a fulltext alternative you can check out PostgreSQL's built in Tsearch2 extension or other options such as Xapian, Solr, Sphinx, etc.
Each of the former engines mentioned have Django apps that makes them easier to integrate: Djapian for Xapian integration or Haystack for multiple integrations in one app.

SOLR Java APi - Adding multiple condition

I am using Solr API to index the records and for search functionality. I am using the following code to search through
ModifiableSolrParams params = new ModifiableSolrParams();
params.set("q", "country_id:("+id+")");
I would like to add one more parameter like state_id and I would like to do logical AND/OR operations and depending on the result the records should be retrieved. I searched through Google, but could not find a way to combine the conditions. Is it possible through the SOLR api? Or am I doing something wrong?
You can make Your Query as Following.....
String qr="cstm_text:"+"devotional";
SolrQuery qry = new SolrQuery(qr);
qry.setIncludeScore(true);
qry.setShowDebugInfo(true);
qry.setRows(1);
qry.setFacet(true);
ModifiableSolrParams params = new ModifiableSolrParams();
params.set("qt", "/spell");
params.set("spellcheck", "on");
params.set(MoreLikeThisParams.MLT,true);
qry.add(params);