Fix/filter by array field (#1813)

* test: filter by association array field

* fix: match operator in pg

* chore: cast
This commit is contained in:
ChengLei Shao 2023-05-07 23:08:41 +08:00 committed by GitHub
parent b3d4e47ef3
commit 7b550ce5aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 83 additions and 7 deletions

View File

@ -5,9 +5,7 @@ import { Collection } from '../../collection';
describe('find with associations', () => {
let db: Database;
beforeEach(async () => {
db = mockDatabase({
tablePrefix: '',
});
db = mockDatabase();
await db.clean({ drop: true });
});
@ -16,6 +14,80 @@ describe('find with associations', () => {
await db.close();
});
it('should filter by association array field', async () => {
const User = db.collection({
name: 'users',
fields: [
{
type: 'string',
name: 'name',
},
{
type: 'hasMany',
name: 'posts',
},
],
});
const Post = db.collection({
name: 'posts',
fields: [
{
type: 'array',
name: 'tags',
},
{
type: 'string',
name: 'title',
},
],
});
await db.sync();
await User.repository.create({
values: [
{
name: 'u1',
posts: [
{
tags: ['t1'],
title: 'u1p1',
},
],
},
],
});
const posts = await Post.repository.find({
filter: {
tags: {
$match: ['t1'],
},
},
});
expect(posts.length).toEqual(1);
const filter = {
$and: [
{
posts: {
tags: {
$match: ['t1'],
},
},
},
],
};
const results = await User.repository.find({
filter,
});
expect(results[0].get('name')).toEqual('u1');
});
it('should filter by association field', async () => {
const User = db.collection({
name: 'users',

View File

@ -11,6 +11,11 @@ const escape = (value, ctx) => {
return sequelize.escape(value);
};
const getQueryInterface = (ctx) => {
const sequelize = ctx.db.sequelize;
return sequelize.getQueryInterface();
};
const sqliteExistQuery = (value, ctx) => {
const fieldName = getFieldName(ctx);
const name = ctx.fullName === fieldName ? `"${ctx.model.name}"."${fieldName}"` : `"${fieldName}"`;
@ -45,10 +50,9 @@ export default {
const fieldName = getFieldName(ctx);
if (isPg(ctx)) {
return {
[Op.contained]: value,
[Op.contains]: value,
};
const name = ctx.fullName === fieldName ? `"${ctx.model.name}"."${fieldName}"` : `"${fieldName}"`;
const queryValue = escape(JSON.stringify(value), ctx);
return Sequelize.literal(`${name} @> ${queryValue}::JSONB AND ${name} <@ ${queryValue}::JSONB`);
}
value = escape(JSON.stringify(value.sort()), ctx);