Skip to content

Commit bd491f4

Browse files
Merge pull request #157 from contentstack/feat/cs-43916-and-operator-query-implementation
Feat/cs 43916 and operator query implementation
2 parents 97cbb6f + bcd84d0 commit bd491f4

File tree

3 files changed

+92
-12
lines changed

3 files changed

+92
-12
lines changed

src/lib/query.ts

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,24 @@ export class Query extends BaseQuery {
201201
return this;
202202
}
203203

204+
/**
205+
* @method notExists
206+
* @memberof Query
207+
* @description Returns the raw (JSON) query based on the filters applied on Query object.
208+
* @example
209+
* import contentstack from '@contentstack/delivery-sdk'
210+
*
211+
* const stack = contentstack.Stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
212+
* const query = stack.contentType("contentTypeUid").entry().query();
213+
* const result = notExists('fieldUid').find()
214+
*
215+
* @returns {Query}
216+
*/
217+
notExists(key: string): Query {
218+
this._parameters[key] = { '$exists': false };
219+
return this;
220+
}
221+
204222
/**
205223
* @method or
206224
* @memberof Query
@@ -215,19 +233,35 @@ export class Query extends BaseQuery {
215233
*
216234
* @returns {Query}
217235
*/
218-
notExists(key: string): Query {
219-
this._parameters[key] = { '$exists': false };
236+
or(...queries: Query[]): Query {
237+
const paramsList: BaseQueryParameters[] = [];
238+
for (const queryItem of queries) {
239+
paramsList.push(queryItem._parameters);
240+
}
241+
this._parameters.$or = paramsList;
220242
return this;
221243
}
222244

223-
or(...queries: Query[]): Query {
224-
const combinedQuery: any = { $or: [] };
225-
for (const query of queries) {
226-
combinedQuery.$or.push(query._parameters);
245+
/**
246+
* @method and
247+
* @memberof Query
248+
* @description Returns the raw (JSON) query based on the filters applied on Query object.
249+
* @example
250+
* import contentstack from '@contentstack/delivery-sdk'
251+
*
252+
* const stack = contentstack.Stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
253+
* const query1 = await contentType.Entry().query().containedIn('fieldUID', ['value']);
254+
* const query2 = await contentType.Entry().query().where('fieldUID', QueryOperation.EQUALS, 'value2');
255+
* const query = await contentType.Entry().query().and(query1, query2).find();
256+
*
257+
* @returns {Query}
258+
*/
259+
and(...queries: Query[]): Query {
260+
const paramsList: BaseQueryParameters[] = [];
261+
for (const queryItem of queries) {
262+
paramsList.push(queryItem._parameters);
227263
}
228-
const newQuery: Query = Object.create(this);
229-
newQuery._parameters = combinedQuery;
230-
231-
return newQuery;
264+
this._parameters.$and = paramsList;
265+
return this;
232266
}
233267
}

test/api/entry-queryables.spec.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,14 @@ describe('Query Operators API test cases', () => {
3737
expect((query.entries[0] as any).multi_line).not.toBeDefined()
3838
}
3939
});
40+
4041
it('should return entries matching any of the conditions - or', async () => {
4142
const query1: Query = await makeEntries('contenttype_uid').query().containedIn('title', ['value']);
4243
const query2: Query = await makeEntries('contenttype_uid').query().where('title', QueryOperation.EQUALS, 'value2');
4344
const query = await makeEntries('contenttype_uid').query().or(query1, query2).find<TEntry>();
4445

4546
if (query.entries) {
46-
expect(query.entries).toHaveLength(2);
47+
expect(query.entries.length).toBeGreaterThan(0);
4748
expect(query.entries[0]._version).toBeDefined();
4849
expect(query.entries[0].locale).toBeDefined();
4950
expect(query.entries[0].uid).toBeDefined();
@@ -54,6 +55,45 @@ describe('Query Operators API test cases', () => {
5455
expect(query.entries[1].title).toBe('value');
5556
}
5657
});
58+
59+
it('should return entries when at least 1 entry condition is matching - or', async () => {
60+
const query1: Query = await makeEntries('contenttype_uid').query().containedIn('title', ['value0']);
61+
const query2: Query = await makeEntries('contenttype_uid').query().where('title', QueryOperation.EQUALS, 'value2');
62+
const query = await makeEntries('contenttype_uid').query().or(query1, query2).find<TEntry>();
63+
64+
if (query.entries) {
65+
expect(query.entries.length).toBeGreaterThan(0);
66+
expect(query.entries[0]._version).toBeDefined();
67+
expect(query.entries[0].locale).toBeDefined();
68+
expect(query.entries[0].uid).toBeDefined();
69+
expect(query.entries[0].title).toBe('value2');
70+
}
71+
});
72+
73+
it('should return entry both conditions are matching - and', async () => {
74+
const query1: Query = await makeEntries('contenttype_uid').query().containedIn('title', ['value']);
75+
const query2: Query = await makeEntries('contenttype_uid').query().where('locale', QueryOperation.EQUALS, 'en-us');
76+
const query = await makeEntries('contenttype_uid').query().and(query1, query2).find<TEntry>();
77+
78+
if (query.entries) {
79+
expect(query.entries.length).toBeGreaterThan(0);
80+
expect(query.entries[0]._version).toBeDefined();
81+
expect(query.entries[0].locale).toBeDefined();
82+
expect(query.entries[0].uid).toBeDefined();
83+
expect(query.entries[0].title).toBe('value');
84+
}
85+
});
86+
87+
it('should return null when any one condition is not matching - and', async () => {
88+
const query1: Query = await makeEntries('contenttype_uid').query().containedIn('title', ['value0']);
89+
const query2: Query = await makeEntries('contenttype_uid').query().where('locale', QueryOperation.EQUALS, 'fr-fr');
90+
const query = await makeEntries('contenttype_uid').query().and(query1, query2).find<TEntry>();
91+
92+
if (query.entries) {
93+
expect(query.entries).toHaveLength(0);
94+
95+
}
96+
});
5797
});
5898

5999
function makeEntries(contentTypeUid = ''): Entries {

test/unit/entry-queryable.spec.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,11 @@ describe('Query Operators API test cases', () => {
3636
const query2: Query = await contentType.Entry().query().where('fieldUID', QueryOperation.EQUALS, 'value2');
3737
const query = await contentType.Entry().query().or(query1, query2);
3838
expect(query._parameters).toStrictEqual({ '$or': [ {'fieldUID': {'$in': ['value']}}, { 'fieldUID': 'value2' } ] });
39-
});
39+
});
40+
it('should return entry when both conditions are matching - and', async () => {
41+
const query1: Query = await contentType.Entry().query().containedIn('fieldUID', ['value']);
42+
const query2: Query = await contentType.Entry().query().where('fieldUID', QueryOperation.EQUALS, 'value2');
43+
const query = await contentType.Entry().query().and(query1, query2);
44+
expect(query._parameters).toStrictEqual({ '$and': [ {'fieldUID': {'$in': ['value']}}, { 'fieldUID': 'value2' } ] });
45+
});
4046
});

0 commit comments

Comments
 (0)