PG: Support for nested contains and containedIn (#4109)
This commit is contained in:
committed by
Florent Vilmart
parent
c2c059f625
commit
c6546218f4
@@ -289,6 +289,40 @@ describe('Parse.Query testing', () => {
|
|||||||
}, done.fail);
|
}, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('nested containedIn string', (done) => {
|
||||||
|
const sender1 = { group: ['A', 'B'] };
|
||||||
|
const sender2 = { group: ['A', 'C'] };
|
||||||
|
const sender3 = { group: ['B', 'C'] };
|
||||||
|
const obj1 = new TestObject({ sender: sender1 });
|
||||||
|
const obj2 = new TestObject({ sender: sender2 });
|
||||||
|
const obj3 = new TestObject({ sender: sender3 });
|
||||||
|
Parse.Object.saveAll([obj1, obj2, obj3]).then(() => {
|
||||||
|
const query = new Parse.Query(TestObject);
|
||||||
|
query.containedIn('sender.group', ['A']);
|
||||||
|
return query.find();
|
||||||
|
}).then((results) => {
|
||||||
|
equal(results.length, 2);
|
||||||
|
done();
|
||||||
|
}, done.fail);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('nested containedIn number', (done) => {
|
||||||
|
const sender1 = { group: [1, 2] };
|
||||||
|
const sender2 = { group: [1, 3] };
|
||||||
|
const sender3 = { group: [2, 3] };
|
||||||
|
const obj1 = new TestObject({ sender: sender1 });
|
||||||
|
const obj2 = new TestObject({ sender: sender2 });
|
||||||
|
const obj3 = new TestObject({ sender: sender3 });
|
||||||
|
Parse.Object.saveAll([obj1, obj2, obj3]).then(() => {
|
||||||
|
const query = new Parse.Query(TestObject);
|
||||||
|
query.containedIn('sender.group', [1]);
|
||||||
|
return query.find();
|
||||||
|
}).then((results) => {
|
||||||
|
equal(results.length, 2);
|
||||||
|
done();
|
||||||
|
}, done.fail);
|
||||||
|
});
|
||||||
|
|
||||||
it("containsAll number array queries", function(done) {
|
it("containsAll number array queries", function(done) {
|
||||||
var NumberSet = Parse.Object.extend({ className: "NumberSet" });
|
var NumberSet = Parse.Object.extend({ className: "NumberSet" });
|
||||||
|
|
||||||
@@ -1379,6 +1413,23 @@ describe('Parse.Query testing', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('nested contains', (done) => {
|
||||||
|
const sender1 = { group: ['A', 'B'] };
|
||||||
|
const sender2 = { group: ['A', 'C'] };
|
||||||
|
const sender3 = { group: ['B', 'C'] };
|
||||||
|
const obj1 = new TestObject({ sender: sender1 });
|
||||||
|
const obj2 = new TestObject({ sender: sender2 });
|
||||||
|
const obj3 = new TestObject({ sender: sender3 });
|
||||||
|
Parse.Object.saveAll([obj1, obj2, obj3]).then(() => {
|
||||||
|
const query = new Parse.Query(TestObject);
|
||||||
|
query.contains('sender.group', 'A');
|
||||||
|
return query.find();
|
||||||
|
}).then((results) => {
|
||||||
|
equal(results.length, 2);
|
||||||
|
done();
|
||||||
|
}, done.fail);
|
||||||
|
});
|
||||||
|
|
||||||
it("startsWith", function(done) {
|
it("startsWith", function(done) {
|
||||||
Parse.Object.saveAll([new TestObject({myString: "zax" + someAscii + "qub"}),
|
Parse.Object.saveAll([new TestObject({myString: "zax" + someAscii + "qub"}),
|
||||||
new TestObject({myString: "start" + someAscii}),
|
new TestObject({myString: "start" + someAscii}),
|
||||||
|
|||||||
@@ -146,6 +146,25 @@ const handleDotFields = (object) => {
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const transformDotFieldToComponents = (fieldName) => {
|
||||||
|
return fieldName.split('.').map((cmpt, index) => {
|
||||||
|
if (index === 0) {
|
||||||
|
return `"${cmpt}"`;
|
||||||
|
}
|
||||||
|
return `'${cmpt}'`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const transformDotField = (fieldName) => {
|
||||||
|
if (fieldName.indexOf('.') === -1) {
|
||||||
|
return `"${fieldName}"`;
|
||||||
|
}
|
||||||
|
const components = transformDotFieldToComponents(fieldName);
|
||||||
|
let name = components.slice(0, components.length - 1).join('->');
|
||||||
|
name += '->>' + components[components.length - 1];
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
const validateKeys = (object) => {
|
const validateKeys = (object) => {
|
||||||
if (typeof object == 'object') {
|
if (typeof object == 'object') {
|
||||||
for (const key in object) {
|
for (const key in object) {
|
||||||
@@ -195,18 +214,26 @@ const buildWhereClause = ({ schema, query, index }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fieldName.indexOf('.') >= 0) {
|
if (fieldName.indexOf('.') >= 0) {
|
||||||
const components = fieldName.split('.').map((cmpt, index) => {
|
let name = transformDotField(fieldName);
|
||||||
if (index === 0) {
|
|
||||||
return `"${cmpt}"`;
|
|
||||||
}
|
|
||||||
return `'${cmpt}'`;
|
|
||||||
});
|
|
||||||
let name = components.slice(0, components.length - 1).join('->');
|
|
||||||
name += '->>' + components[components.length - 1];
|
|
||||||
if (fieldValue === null) {
|
if (fieldValue === null) {
|
||||||
patterns.push(`${name} IS NULL`);
|
patterns.push(`${name} IS NULL`);
|
||||||
} else {
|
} else {
|
||||||
patterns.push(`${name} = '${fieldValue}'`);
|
if (fieldValue.$in) {
|
||||||
|
const inPatterns = [];
|
||||||
|
name = transformDotFieldToComponents(fieldName).join('->');
|
||||||
|
fieldValue.$in.forEach((listElem) => {
|
||||||
|
if (typeof listElem === 'string') {
|
||||||
|
inPatterns.push(`"${listElem}"`);
|
||||||
|
} else {
|
||||||
|
inPatterns.push(`${listElem}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
patterns.push(`(${name})::jsonb @> '[${inPatterns.join(',')}]'::jsonb`);
|
||||||
|
} else if (fieldValue.$regex) {
|
||||||
|
// Handle later
|
||||||
|
} else {
|
||||||
|
patterns.push(`${name} = '${fieldValue}'`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (fieldValue === null) {
|
} else if (fieldValue === null) {
|
||||||
patterns.push(`$${index}:name IS NULL`);
|
patterns.push(`$${index}:name IS NULL`);
|
||||||
@@ -298,6 +325,10 @@ const buildWhereClause = ({ schema, query, index }) => {
|
|||||||
values.push(fieldName, JSON.stringify(baseArray));
|
values.push(fieldName, JSON.stringify(baseArray));
|
||||||
index += 2;
|
index += 2;
|
||||||
} else {
|
} else {
|
||||||
|
// Handle Nested Dot Notation Above
|
||||||
|
if (fieldName.indexOf('.') >= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const inPatterns = [];
|
const inPatterns = [];
|
||||||
values.push(fieldName);
|
values.push(fieldName);
|
||||||
baseArray.forEach((listElem, listIndex) => {
|
baseArray.forEach((listElem, listIndex) => {
|
||||||
@@ -466,10 +497,11 @@ const buildWhereClause = ({ schema, query, index }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const name = transformDotField(fieldName);
|
||||||
regex = processRegexPattern(regex);
|
regex = processRegexPattern(regex);
|
||||||
|
|
||||||
patterns.push(`$${index}:name ${operator} '$${index + 1}:raw'`);
|
patterns.push(`$${index}:raw ${operator} '$${index + 1}:raw'`);
|
||||||
values.push(fieldName, regex);
|
values.push(name, regex);
|
||||||
index += 2;
|
index += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user