Search by first character in a column Typeorm PostgreSQL - postgresql

I have a company table where I want to search companies by their name of the first letter. In my front end I have a series of letters as checkboxes from A to z and I am passing selected letters as a,b,c in my request body.
If I execute this raw query then it is working, but how I can write this in typeorm querybuilder
select * FROM companies WHERE lower(substring(name from 1 for 1)) = ANY (ARRAY['m'])
I have tried with the query below -
public async getCompanies(
pageOptionsQuery: CompanyPageOptionsDto,
): Promise<Company[]> {
const queryBuilder = this._companyRepository
.createQueryBuilder()
.select('*');
if (!!pageOptionsQuery.filter_by) {
//pageOptionsQuery.filter_by is like series of selected letters
//a,b,c
const filters = pageOptionsQuery.filter_by.split(',');
queryBuilder.where('LOWER(name) IN (:...filters )', {
filters: filters,
});
}
return queryBuilder.getRawMany();
}

This is what I have come up with -
public async getCompanies(
pageOptionsQuery: CompanyPageOptionsDto,
): Promise<Company[]> {
const queryBuilder = this._companyRepository
.createQueryBuilder()
.select('*');
if (!!pageOptionsQuery.filter_by) {
//pageOptionsQuery.filter_by is like series of selected letters
//a,b,c
const filters = pageOptionsQuery.filter_by.split(',');
queryBuilder.where(
'LOWER(SUBSTRING(name, 1, 1)) IN (:...filters)',
{
filters,
},
);
}
return queryBuilder.getRawMany();
}

Related

Prisma: Finding items where two fields have the same value

I would like to find items in a Prisma db where the values for two columns are the same. The use case is to compare the 'created_at' and 'updated_at' fields to find items that have never been updated after their initial creation. In raw SQL I would do something like:
select updated_at,
cast(sign(sum(case when updated_at = created_at then
1
else
0
end)) as int) as never_modified
from tab
group by updated_at
Is it possible to achieve this in Prisma?
You would need to use Raw Queries to compare time values from the same table.
Here's an example of how you could achieve this, assuming a PostgreSQL database for the following query.
import { PrismaClient } from '#prisma/client'
const prisma = new PrismaClient()
async function initiateDatesComparisonRawQuery() {
const response =
await prisma.$queryRaw`SELECT * FROM "public"."Project" WHERE "created_at" = "updated_at";`;
console.log(response);
}
await initiateDatesComparisonRawQuery();
you can use the preview feature fieldReference of prisma.
schema.prisma
generator client {
provider = "prisma-client-js"
previewFeatures = ["fieldReference"]
}
your code
prisma.project.findMany({
where: { created_at: prisma.project.fields.updated_at }
})

Why is double underscore needed here for accessing table field?

I came across a GitHub issue about sorting rows with TypeORM. I found this comment did work for my problem.
Quote:
async sortWithRelations(entityRepository) {
// Assuming repository classname is RepoX
let repoOptions = {
relations: ['relationA', 'relationB'],
where: qb => {
// Filter if required
qb.where('RepoX__relationA.fieldY = :val', {val: 'searchedValue'});
// Then sort
qb.orderBy({
'RepoX__relationA.fieldYYY': 'DESC',
'RepoX__relationB.fieldZZZ': 'DESC'
// '{repositoryClassName}__{relationName}.fieldName
// [+ __{childRelations} for every child relations]
});
}
};
However, I have no idea why RepositoryClassName__ accompanied with double underscore is needed to access the table column?
'RelationName.FieldName': 'DESC' will result in error instead.

Why is my dynamic sql resulting in the error shown below?

I am trying to build a sql statement dynamically and this is one variation of the result.
sqlQuery {
name: 'fetch-products',
text: 'select * from products where category =
$1 and designer in $2',
values: [ 'WOMENSCLOTHING', "('Adjavon', 'ALC', 'Adele', 'Bagley')" ]
}
I build the sql with the following code segment:
const {
category,
designers,
} = JSON.parse(filters);
let values = [category];
let text = 'select * from products where category = $1';
if(designers) {
text = text + ' and designer in $2';
values.push(designers);
}
I execute it in the following segment:
try {
const allProducts = await pool.query(sqlQuery);
res.status(200).json(allProducts.rows);
} catch (error) {
console.error(error);
return res.status(500).send('Problems gettting products by category.')
}
And get the following error:
error: syntax error at or near "$2"
I am thinking the error may be the double quotes placed around designer when it is pushed on the values array:
values: [ 'WOMENSCLOTHING', "('Adjavon', 'ALC', 'Adele', 'Bagley')" ]
I don't know what library you are using exactly, but the values property looks highly suspicious.
sqlQuery {
name: 'fetch-products',
text: 'select * from products where category =
$1 and designer in $2',
values: [ 'WOMENSCLOTHING', "('Adjavon', 'ALC', 'Adele', 'Bagley')" ]
}
If your drivr/library supports this, the second element in the array should be an actual array and not a string like '("foo", "bat")'. How is the driver supposed to know this is meant as a list and not a single string that has this value?
I guess in a nutshell you have to bring the query in this form:
const query = 'select * from products where category = $1 and designer in ($2, $3, $4, $5)'
const values = [ 'WOMENSCLOTHING', 'Adjavon', 'ALC', 'Adele', 'Bagley' ]
That requires some extra work on the backend to map the values and bring them into the right shape.
I guess you could get that done with something like this:
const category = 'icecream'
const designers = ['jim', 'maria']
let values = [category];
let text = 'select * from products where category = $1';
if (designers) {
text += ` and designer in (${designers.map((d, i) => `$${i+2}`).join(', ')})`;
values = [...values, ...designers];
}
console.log(text);
console.log(values);

How to get the number of entries in a table using flutter_moor?

When I am adding an entry to the table, I need to know the number of elements in the table.
onPressed: () {
final db = Provider.of<AppDb>(context);
final habitCount = 0; /* Number of entries in the "Habits" table */
db.into(db.habits)
.insert(HabitsCompanion.insert(name: "Sleep", order: habitCount * 2 ));
},
How can I do this as easily as possible?
You can create DAO to manage all queries. Here I am giving you an example of todos table which is used in documentation.
In this example, you can create a manual query by the queries key.
#UseDao(tables: [Todos], queries: {'totalTodos': 'SELECT COUNT(*) FROM todos;'})
class TodoDao extends DatabaseAccessor<MyDatabase> with _$TodoDaoMixin {
final MyDatabase database;
TodoDao(this.database) : super(database);
Future<int> getTotalRecords() {
return totalTodos().getSingle();
}
}
How to use:
Selectable<int> total = TodoDao(database).totalTodos();
total.getSingle().then((value) => print('Records: $value'));
Hope you will understand the example. Do let me know if you have any questions.

Generate jpql queries dynamically based on values provided/not provided from multiple choice lists

I have four choice lists on my HTML page and I'm retrieving data when the choices are selected. How do I dynamically create a jqpl query based on the selection on the choice lists.
In my case, there are 4 choice lists and a user can either select options from all the lists or a combination of them. How do I write my query in this scenario?
My query is something like
SELECT x FROM tablename x WHERE x.column1= :choice1 AND x.column2 = :choice2 AND x.column3 = :choice3 AND x.column4 = :choice4
I assume that you may try this Criteria API
Very simple. You can use a Map to save the paremeters in each condition that verify if the choiceX exists.
Example:
String jpql = "SELECT x FROM tablename x WHERE 1 = 1 ";
Map<String, Object> parameters = new HashMap<>();
if (choice1 != null) {
jpql += "x.column1 = :choice1 ";
parameters.put("choice1", choice1);
}
if (choice2 != null) {
jpql += "x.column2 = :choice2 ";
parameters.put("choice2", choice2);
}
Query query = entityManager.createQuery(jpql);
for (Entry<String, Object> entry : parameters.entrySet()) {
query.setParameter(entry.getKey(), entry.getValue());
}
return query.getResultList();