How to create where statement based on result of multiset - kotlin

So, i would like to filter my query by exact match in result of multiset. Any ideas how to do it in JOOQ?
Example:
val result = dsl.select(
PLANT_PROTECTION_REGISTRATION.ID,
PLANT_PROTECTION_REGISTRATION.REGISTRATION_NUMBER,
PLANT_PROTECTION_REGISTRATION.PLANT_PROTECTION_ID,
multiset(
select(
PLANT_PROTECTION_APPLICATION.ORGANISM_ID,
PLANT_PROTECTION_APPLICATION.ORGANISM_TEXT
).from(PLANT_PROTECTION_APPLICATION)
.where(PLANT_PROTECTION_APPLICATION.REGISTRATION_ID.eq(PLANT_PROTECTION_REGISTRATION.ID))
).`as`("organisms")
).from(PLANT_PROTECTION_REGISTRATION)
// here i would like to filter my result only for records that their organisms contain specific
// organism id
.where("organisms.organism_id".contains(organismId))

I've explained the following answer more in depth in this blog post
About the MULTISET value constructor
The MULTISET value constructor operator is so powerful, we'd like to use it everywhere :) But the way it works is that it creates a correlated subquery, which produces a nested data structure, which is hard to further process in the same SQL statement. It's not impossible. You could create a derived table and then unnest the MULTISET again, but that would probably be quite unwieldy. I've shown an example using native PostgreSQL in that blog post
Alternative using MULTISET_AGG
If you're not nesting things much more deeply, how about using the lesser known and lesser hyped MULTISET_AGG alternative, instead? In your particular case, you could do:
// Using aliases to make things a bit more readable
val ppa = PLANT_PROTECTION_APPLICATION.as("ppa");
// Also, implicit join helps keep things more simple
val ppr = ppa.plantProtectionRegistration().as("ppr");
dsl.select(
ppr.ID,
ppr.REGISTRATION_NUMBER,
ppr.PLANT_PROTECTION_ID,
multisetAgg(ppa.ORGANISM_ID, ppa.ORGANISM_TEXT).`as`("organisms"))
.from(ppa)
.groupBy(
ppr.ID,
ppr.REGISTRATION_NUMBER,
ppr.PLANT_PROTECTION_ID)
// Retain only those groups which contain the desired ORGANISM_ID
.having(
boolOr(trueCondition())
.filterWhere(ppa.ORGANISM_ID.eq(organismId)))
.fetch()

Related

Couchbase Query Name Alias

Actually I am working with Couchbase N1Ql Query for retrieving data from db which has calculation in it
a sample similar model of my query is below:
SELECT 2+1 AS Greeting from something where Greeting>1;
The Error I'm getting is :
Ambiguous reference to field Greeting.
But if I modify This like this:
SELECT 2+1 AS Greeting from something where 2+1>1
this is working, but this one is not good solution as it involves a lot of computations.
Can any one help me out in optimizing this query?
As #DinishDB mentioned projection Alias can't be used in WHERE.
SELECT Greeting
FROM something
LET Greeting = 2+1
WHERE Greeting > 1
LET variables can be derived from document, can be chained.
If let variables used in WHERE it will inline and choose index selection. Also variables evaluated before WHERE FILTER. If not used in WHERE it evaluated post FILTER to save evaluation. In above case it is constant. So happens FILTER is evaluate false, No documents will be fetched.
OR
WITH Greeting AS (2+1)
SELECT Greeting
FROM something
WHERE Greeting > 1
If constant use WITH clause one time evaluation vs LET every document evaluation.

undefined method `and' for #<Arel::Attributes::Attribute

I'm having an issue getting a query to work.
I'm essentially trying to write something like the following SQL, with the literal 5 replaced with a variable:
SELECT *
FROM "my_table"
WHERE 5 BETWEEN "my_table"."minimum" AND "my_table"."maximum"
This is what I have at the moment:
MyModel.where(
Arel::Nodes::Between.new(
my_variable, (MyModel.arel_table[:minimum]).and(MyModel.arel_table[:maximum])
)
)
Please ignore the way I am using arel_table, the actual query has multiple joins and is more complex, but this is the most minimum reproducible example I have to demonstrate the problem.
The error, as in the subject of the question is as follows:
undefined method `and' for #<Arel::Attributes::Attribute:0x00007f55e15514f8>
and method is for Arel::Nodes::Node i.e. MyModel.arel_attribute[:name].eq(Arel::Nodes::Quoted.new('engineersmnky')) This is an Arel::Nodes::Equality and you can chain with and.
That being said you can construct an Arel::Nodes::And for yourself via
Arel::Nodes::And.new([left,right])
Then we can pass this to the Between class like so
Arel::Nodes::Between.new(
Arel::Nodes::Quoted.new(my_variable),
Arel::Nodes::And.new([
MyModel.arel_table[:minimum],
MyModel.arel_table[:maximum]])
)
The Arel::Nodes::Quoted (also: Arel::Nodes.build_quoted(arg)) is not needed in your case since your my_variable is an Integer which can be visited and will be treated as an Arel::Nodes::SqlLiteral but I find it best to let arel decide how to handle the quoting in case your my_variable ends up being some other un-visitable Object
There are other ways to create a Between and other ways to create an And depending on what objects you are dealing with.
between is a Arel::Predication and these predications are available to Arel::Nodes::Attribute objects e.g.
MyModel.arel_table[:minimum].between([1,6])
and as mentioned is available to Arel::Nodes::Node and instances of this class provides a convenience method (create_and) for creating an And so we could do the following:
Arel::Nodes::Node.new.create_and([
MyModel.arel_table[:minimum],
MyModel.arel_table[:maximum]])
There are a number of other ways to hack this functionality together by using other Arel classes but this should get you headed in the right direction.

Get common ManyToMany objects with django extra select

class Seller(object):
type = ...
name = ...
cars = models.ManyToManyField(Car)
class PotentialBuyer(object):
name = ...
cars = models.ManyToManyField(Car)
class Car(object):
extra_field = ...
extra_field2 = ...
Suppose I have a relationship like this. I would like to use extra queryset modifier to get the list of cars that are already been picked out by PotentialBuyers when I fetch a seller object. I suppose the query queryset will something like this.
def markPending(self)
return self.extra(select={'pending': 'select images from PotentialBuyer as t ...'})
How can I accomplish this? Is there a better way? I could fetch the seller object and the potential object and do sets, but I'd think it would be cleaner to make it handled by the database. I am using PostgreSQL 9.5.
I think the Exists subquery expression will do what you want. Or at least it'll get you started on the right path. Docs Or you might want to use an aggregate to count the number of them.
Edit: If you need to select the full objects rather than the count, existence or a single entity, then use a Prefetch instance in prefetch_related. https://docs.djangoproject.com/en/2.0/ref/models/querysets/#django.db.models.Prefetch
Not quite the answer, but this is the solution I ended up with and I am satisfied by the performance. Perhaps someone can answer the question later :
from api.models import PotentialBuyer
potentials = PotentialBuyer.objects.filter(owner=user_id, default=True).first().cars.all()
Car.objects.filter(....).annotate(pending=Case(When(id__in=potentials, then=Value(True)), default=Value(False), output_field=BooleanField()))

elastic-search on/and nesting possible?

Can and/or be nested in filters?
I want to filter something like this... a=1 AND ( d=NULL OR d>5 )
Can anyone help?
You can use a Lucene query string like this in elastic search:
http://www.elasticsearch.org/guide/reference/query-dsl/query-filter.html
and here is a reference to how you can use () for grouping ... one thing to note is the I found prefixing group statements with the + must have symbol returns more accurate results.
http://lucene.apache.org/java/3_2_0/queryparsersyntax.html
grouping is at the end.
... oh and if you going to use greater than RangeQuery can cover this case by
setting either the upper or lower term to null.
J.
This may be a bit late, but if anyone else is looking for this, I found that search word AND filters are easy to add. Just use more words in the query and separate them with space.
Scala Example:
val queryString = client.prepareSearch().setQuery(QueryBuilders.matchQuery("json.path.to.node", "sky car")).setSize(MAX_RESULTS)
val response = queryString.execute().actionGet()
Now response will have all results which containt both sky AND car

NHibernate: DetachedCriteria nesting more than once

I can't get DetachedCriteria to work properly after nesting more than once, the reason being that the DetatchedCriteria can only access aliased entities one layer higher.
The following doesn't work, for example:
var secondNestedCriteria = DetachedCriteria.For<Baz>("baz")
.SetProjection(Projections.Id())
.Add(Restrictions.EqProperty("baz.FooName", "foo.Name") // Doesn't work
.Add(Restrictions.EqProperty("baz.BarName", "bar.Name");
var firstNestedCriteria = DetachedCriteria.For<Bar>("bar")
.SetProjection(Projections.Id())
.Add(Restrictions.EqProperty("bar.FooName", "foo.Name")
.Add(Subqueries.Exists(secondNestedCriteria);
var criteria = Session.CreateCriteria<Foo>("foo")
.Add(Subqueries.Exists(firstNestedCriteria)
.List<Foo>();
Does anyone know a workaround that doesn't involve using HQL?
I never had this problem, I usually use PropertyIn to join subqueries, but you can't always do the same.
In this particular case, you could fix it by using the property of the second query:
var secondNestedCriteria = DetachedCriteria.For<Baz>("baz")
.SetProjection(Projections.Id())
.Add(Restrictions.EqProperty("baz.FooName", "bar.FooName") // is equal to foo.Name
.Add(Restrictions.EqProperty("baz.BarName", "bar.Name");
If this doesn't help in your real case, you may ask for a solution of the real case. I don't think that there is a general solution.