Redisearch equivalent for a MySQL query - redis

I'm looking for the Redisearch equivalent of the following query:
NOT (topic_id = '123' AND post_id <= '456')
I tried the following - it works but doesn't look like the most elegant solution:
-(#topic_id:[123 123] #post_id:[-inf 456])
topic_id and post_id are NUMERIC and SORTABLE
Thanks for your help!

Chris,
Your query looks perfectly valid, the only simplification I would apply is:
-(#topic_id:123 #post_id:[-inf 456])
To avoid repeating the 123 value. The other option would be to use DeMorgan's law and rewrite your NOT(A AND B) to (!A OR !B) but I don't think that would buy you anything, and in this case it would make it harder to read I think.

Related

postgresql where conditional, mixin "AND" "OR"

I need to get the data from a DB and match two columns: Key and name, but I cant get it to work, if I use AND on both conditions:
...where lower(items.key_) SIMILAR TO lower('memory.size')
and lower(items.name) SIMILAR TO lower('Memory Utilization%')
and history.clock > '2020-08-12 03:05:32'
the query doesnt work because when items.key is similar to memory.size, items.name will never be similar to "Memory Utilization", so I try to do it with OR:
...where lower(items.key_) SIMILAR TO lower('memory.size')
or lower(items.name) SIMILAR TO lower('Memory Utilization%')
and history.clock > '2020-08-12 03:05:32'
But it doesnt work either.
Any Ideas?
SIMILAR TO is not really the operator you want. You are using %, so that suggests LIKE:
where (lower(items.key_) like lower('memory.size') or
lower(items.name) like lower('Memory Utilization%')
) and history.clock > '2020-08-12 03:05:32'

How can I create a SELECT EXISTS (subquery) with jOOQ?

I want to build and execute a query like this with jOOQ.
SELECT EXISTS( subquery )
For exemple:
SELECT EXISTS(SELECT 1 FROM icona_etiqueta WHERE pvp IS NULL AND unitat_venda = 'GRAMS')
How can I do it? Can it be done?
Found it. I was looking for a selectExists method and got confused by the DSL.exists() predicate constructor.
There is a much more convenient fetchExists(subquery).
My specific example is resolved like this:
create.fetchExists(
create.selectOne()
.from(ICONA_ETIQUETA)
.where(ICONA_ETIQUETA.PVP.isNull(),
ICONA_ETIQUETA.UNITAT_VENDA.eq('GRAMS'))
);
Which directly returns a boolean.
Your own solution is the most convenient approach to what you want to be doing. A more general approach is to use:
create.select(field(exists(...)));
Where you wrap a Condition (created by DSL.exists(Select)) in a Field using DSL.field(Condition). As of jOOQ 3.9, Field<Boolean> and Condition are not the same types. This has changed in the jOOQ 3.17 with #11969. You can now also just write:
create.select(exists(...));

How to custom sort this data in SQL Server 2012?

I have some hard time figuring it out how to custom sort data below the way I want to. Meaning it should be in order like this:
201-1-1
201-1-2
201-1-3
.......
201-2-1
and so on if you know what I mean.
Instead I'm getting this sort executing below code:
select *
from test.dbo.accounts
order by account_name asc
Output:
201-10-1
201-10-2
201-1-1
201-11-1
201-11-2
201-11-3
201-11-4
201-11-6
201-1-2
201-12-1
201-12-2
201-12-3
201-12-4
201-12-6
201-1-3
201-13-1
201-13-2
201-13-3
201-13-4
201-13-6
201-1-4
201-14-1
201-14-2
201-14-4
201-14-6
201-15-1
201-15-2
201-15-3
201-15-4
201-15-6
201-1-6
201-16-1
201-16-2
201-16-3
201-16-4
201-16-6
201-16-7
201-1-7
201-17-1
201-17-2
201-17-4
201-17-6
201-18-1
201-18-2
201-18-3
201-18-4
201-18-6
201-19-1
Thanks
For your sample data, this following trick will work:
order by len(account_name), account_name
This only works because the only variable length component is the second component and because the hyphen is "smaller" than digits.
You should normalize the accounts names so all the components are the same length, by left padding the numbers with zeros.
Ugh. String manipulation in SQL can be extremely cumbersome. There might be a better way to do this, but this does seem to work.
select accoutn_name
from test.dbo.accounts
order by left(account_name,charindex('-',account_name,1)-1)
,replace(right(left(account_name,CHARINDEX('-',account_name,1)+2),2),'-', '')
,REPLACE(right(account_name,2),'-','')
BTW, this is a very expensive process to run. If it's productionalized, you'll want to come up with a better solution.

Doctrine Query <timestamp

I have a colum "datetime", like this: 2012-06-04 15:40:20.
I want to create a query in Doctrine that I get the data of previous time. Less than 2012-06-04 15:40:20. How can I realize that in Doctrine.
Sorry, I just have no clue.
If I understand your question correctly, I believe the syntax is just:
$datetime = // your timestamp
->where('t.somefield < ?', date('Y-m-d H:i:s', strtotime($datetime))
I am not familiar with Doctrine, but here is standard SQL to do what you want:
select *
from t
where t.datetime in (select max(datetime)
from t
where datetime < '2012-06-04 15:40:20'
)
If Doctrine supports standard SQL syntax, then something like this would work (you might have to input the date/time constant in a different way).

Django select only rows with duplicate field values

suppose we have a model in django defined as follows:
class Literal:
name = models.CharField(...)
...
Name field is not unique, and thus can have duplicate values. I need to accomplish the following task:
Select all rows from the model that have at least one duplicate value of the name field.
I know how to do it using plain SQL (may be not the best solution):
select * from literal where name IN (
select name from literal group by name having count((name)) > 1
);
So, is it possible to select this using django ORM? Or better SQL solution?
Try:
from django.db.models import Count
Literal.objects.values('name')
.annotate(Count('id'))
.order_by()
.filter(id__count__gt=1)
This is as close as you can get with Django. The problem is that this will return a ValuesQuerySet with only name and count. However, you can then use this to construct a regular QuerySet by feeding it back into another query:
dupes = Literal.objects.values('name')
.annotate(Count('id'))
.order_by()
.filter(id__count__gt=1)
Literal.objects.filter(name__in=[item['name'] for item in dupes])
This was rejected as an edit. So here it is as a better answer
dups = (
Literal.objects.values('name')
.annotate(count=Count('id'))
.values('name')
.order_by()
.filter(count__gt=1)
)
This will return a ValuesQuerySet with all of the duplicate names. However, you can then use this to construct a regular QuerySet by feeding it back into another query. The django ORM is smart enough to combine these into a single query:
Literal.objects.filter(name__in=dups)
The extra call to .values('name') after the annotate call looks a little strange. Without this, the subquery fails. The extra values tricks the ORM into only selecting the name column for the subquery.
try using aggregation
Literal.objects.values('name').annotate(name_count=Count('name')).exclude(name_count=1)
In case you use PostgreSQL, you can do something like this:
from django.contrib.postgres.aggregates import ArrayAgg
from django.db.models import Func, Value
duplicate_ids = (Literal.objects.values('name')
.annotate(ids=ArrayAgg('id'))
.annotate(c=Func('ids', Value(1), function='array_length'))
.filter(c__gt=1)
.annotate(ids=Func('ids', function='unnest'))
.values_list('ids', flat=True))
It results in this rather simple SQL query:
SELECT unnest(ARRAY_AGG("app_literal"."id")) AS "ids"
FROM "app_literal"
GROUP BY "app_literal"."name"
HAVING array_length(ARRAY_AGG("app_literal"."id"), 1) > 1
Ok, so for some reason none of the above worked for, it always returned <MultilingualQuerySet []>. I use the following, much easier to understand but not so elegant solution:
dupes = []
uniques = []
dupes_query = MyModel.objects.values_list('field', flat=True)
for dupe in set(dupes_query):
if not dupe in uniques:
uniques.append(dupe)
else:
dupes.append(dupe)
print(set(dupes))
If you want to result only names list but not objects, you can use the following query
repeated_names = Literal.objects.values('name').annotate(Count('id')).order_by().filter(id__count__gt=1).values_list('name', flat='true')