fix: array $noneOf with null (#220)

* fix: array $noneOf with null

* fix: mysql test
This commit is contained in:
ChengLei Shao 2022-03-04 18:13:48 +08:00 committed by GitHub
parent 5233d00373
commit 534a6e43ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 17 deletions

View File

@ -26,14 +26,14 @@ describe('array field operator', function () {
t1 = await Test.repository.create({
values: {
selected: [1, 2, 'a', 'b'],
selected: ['1', '2', 'a', 'b'],
name: 't1',
},
});
t2 = await Test.repository.create({
values: {
selected: [11, 22, 'aa', 'bb', 'cc'],
selected: ['11', '22', 'aa', 'bb', 'cc'],
name: 't2',
},
});
@ -133,7 +133,7 @@ describe('array field operator', function () {
test('$match', async () => {
const filter1 = await Test.repository.find({
filter: {
'selected.$match': [2, 1, 'a', 'b'],
'selected.$match': ['2', '1', 'a', 'b'],
},
});
@ -146,7 +146,7 @@ describe('array field operator', function () {
filter: {
$and: [
{
selected: { $match: [2, 1, 'a', 'b'] },
selected: { $match: ['2', '1', 'a', 'b'] },
},
],
},
@ -159,7 +159,7 @@ describe('array field operator', function () {
test('$notMatch', async () => {
const filter2 = await Test.repository.find({
filter: {
'selected.$notMatch': [1, 2, 'a', 'b'],
'selected.$notMatch': ['1', '2', 'a', 'b'],
},
});
@ -193,6 +193,16 @@ describe('array field operator', function () {
expect(filter3[0].get('name')).toEqual(t2.get('name'));
});
test('$anyOf with multiple items', async () => {
const filter3 = await Test.repository.find({
filter: {
'selected.$anyOf': ['aa', 'a', '1'],
},
});
expect(filter3.length).toEqual(2);
});
test('$noneOf', async () => {
const filter = await Test.repository.find({
filter: {
@ -204,6 +214,24 @@ describe('array field operator', function () {
expect(filter[0].get('name')).toEqual(t1.get('name'));
});
test('$noneOf with null', async () => {
const t3 = await Test.repository.create({
values: {
name: 't3',
selected: null,
},
});
const filter = await Test.repository.find({
filter: {
'selected.$noneOf': ['a', 'aa', '1'],
},
});
expect(filter.length).toEqual(1);
expect(filter[0].get('name')).toEqual(t3.get('name'));
});
test('$empty', async () => {
const t3 = await Test.repository.create({
values: {

View File

@ -12,6 +12,7 @@ export class ArrayField extends Field {
sortValue(model) {
const oldValue = model.get(this.options.name);
if (oldValue) {
const newValue = oldValue.sort();
model.set(this.options.name, newValue);

View File

@ -81,9 +81,12 @@ export default {
const fieldName = getFieldName(ctx);
if (isPg(ctx)) {
const queryValue = JSON.stringify(value).replace("'", "''");
return Sequelize.literal(`${fieldName} @> ${escape(queryValue, ctx)}::JSONB`);
return Sequelize.literal(
`${fieldName} ?| ${escape(
value.map((i) => `${i}`),
ctx,
)}`,
);
}
if (isMySQL(ctx)) {
@ -98,23 +101,29 @@ export default {
},
$noneOf(value, ctx) {
let where;
if (isPg(ctx)) {
const fieldName = getFieldName(ctx);
// pg single quote
const queryValue = JSON.stringify(value).replace("'", "''");
return Sequelize.literal(`not (${fieldName} @> ${escape(queryValue, ctx)}::JSONB)`);
}
if (isMySQL(ctx)) {
where = Sequelize.literal(
`not (${fieldName} ?| ${escape(
value.map((i) => `${i}`),
ctx,
)})`,
);
} else if (isMySQL(ctx)) {
const fieldName = getFieldName(ctx);
value = escape(JSON.stringify(value), ctx);
return Sequelize.literal(`NOT JSON_OVERLAPS(${fieldName}, ${value})`);
where = Sequelize.literal(`NOT JSON_OVERLAPS(${fieldName}, ${value})`);
} else {
const subQuery = sqliteExistQuery(value, ctx);
where = Sequelize.literal(`not ${subQuery}`);
}
const subQuery = sqliteExistQuery(value, ctx);
return {
[Op.and]: [Sequelize.literal(`not ${subQuery}`)],
[Op.or]: [where, { [Op.is]: null }],
};
},