Skip to content

Commit

Permalink
Merge pull request #157 from contentstack/feat/cs-43916-and-operator-…
Browse files Browse the repository at this point in the history
…query-implementation

Feat/cs 43916 and operator query implementation
  • Loading branch information
harshithad0703 authored Mar 12, 2024
2 parents cfe3241 + 432d11f commit 82987b9
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 12 deletions.
54 changes: 44 additions & 10 deletions src/lib/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,24 @@ export class Query extends BaseQuery {
return this;
}

/**
* @method notExists
* @memberof Query
* @description Returns the raw (JSON) query based on the filters applied on Query object.
* @example
* import contentstack from '@contentstack/delivery-sdk'
*
* const stack = contentstack.Stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
* const query = stack.contentType("contentTypeUid").entry().query();
* const result = notExists('fieldUid').find()
*
* @returns {Query}
*/
notExists(key: string): Query {
this._parameters[key] = { '$exists': false };
return this;
}

/**
* @method or
* @memberof Query
Expand All @@ -215,19 +233,35 @@ export class Query extends BaseQuery {
*
* @returns {Query}
*/
notExists(key: string): Query {
this._parameters[key] = { '$exists': false };
or(...queries: Query[]): Query {
const paramsList: BaseQueryParameters[] = [];
for (const queryItem of queries) {
paramsList.push(queryItem._parameters);
}
this._parameters.$or = paramsList;
return this;
}

or(...queries: Query[]): Query {
const combinedQuery: any = { $or: [] };
for (const query of queries) {
combinedQuery.$or.push(query._parameters);
/**
* @method and
* @memberof Query
* @description Returns the raw (JSON) query based on the filters applied on Query object.
* @example
* import contentstack from '@contentstack/delivery-sdk'
*
* const stack = contentstack.Stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
* const query1 = await contentType.Entry().query().containedIn('fieldUID', ['value']);
* const query2 = await contentType.Entry().query().where('fieldUID', QueryOperation.EQUALS, 'value2');
* const query = await contentType.Entry().query().and(query1, query2).find();
*
* @returns {Query}
*/
and(...queries: Query[]): Query {
const paramsList: BaseQueryParameters[] = [];
for (const queryItem of queries) {
paramsList.push(queryItem._parameters);
}
const newQuery: Query = Object.create(this);
newQuery._parameters = combinedQuery;

return newQuery;
this._parameters.$and = paramsList;
return this;
}
}
42 changes: 41 additions & 1 deletion test/api/entry-queryables.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,14 @@ describe('Query Operators API test cases', () => {
expect((query.entries[0] as any).multi_line).not.toBeDefined()
}
});

it('should return entries matching any of the conditions - or', async () => {
const query1: Query = await makeEntries('contenttype_uid').query().containedIn('title', ['value']);
const query2: Query = await makeEntries('contenttype_uid').query().where('title', QueryOperation.EQUALS, 'value2');
const query = await makeEntries('contenttype_uid').query().or(query1, query2).find<TEntry>();

if (query.entries) {
expect(query.entries).toHaveLength(2);
expect(query.entries.length).toBeGreaterThan(0);
expect(query.entries[0]._version).toBeDefined();
expect(query.entries[0].locale).toBeDefined();
expect(query.entries[0].uid).toBeDefined();
Expand All @@ -54,6 +55,45 @@ describe('Query Operators API test cases', () => {
expect(query.entries[1].title).toBe('value');
}
});

it('should return entries when at least 1 entry condition is matching - or', async () => {
const query1: Query = await makeEntries('contenttype_uid').query().containedIn('title', ['value0']);
const query2: Query = await makeEntries('contenttype_uid').query().where('title', QueryOperation.EQUALS, 'value2');
const query = await makeEntries('contenttype_uid').query().or(query1, query2).find<TEntry>();

if (query.entries) {
expect(query.entries.length).toBeGreaterThan(0);
expect(query.entries[0]._version).toBeDefined();
expect(query.entries[0].locale).toBeDefined();
expect(query.entries[0].uid).toBeDefined();
expect(query.entries[0].title).toBe('value2');
}
});

it('should return entry both conditions are matching - and', async () => {
const query1: Query = await makeEntries('contenttype_uid').query().containedIn('title', ['value']);
const query2: Query = await makeEntries('contenttype_uid').query().where('locale', QueryOperation.EQUALS, 'en-us');
const query = await makeEntries('contenttype_uid').query().and(query1, query2).find<TEntry>();

if (query.entries) {
expect(query.entries.length).toBeGreaterThan(0);
expect(query.entries[0]._version).toBeDefined();
expect(query.entries[0].locale).toBeDefined();
expect(query.entries[0].uid).toBeDefined();
expect(query.entries[0].title).toBe('value');
}
});

it('should return null when any one condition is not matching - and', async () => {
const query1: Query = await makeEntries('contenttype_uid').query().containedIn('title', ['value0']);
const query2: Query = await makeEntries('contenttype_uid').query().where('locale', QueryOperation.EQUALS, 'fr-fr');
const query = await makeEntries('contenttype_uid').query().and(query1, query2).find<TEntry>();

if (query.entries) {
expect(query.entries).toHaveLength(0);

}
});
});

function makeEntries(contentTypeUid = ''): Entries {
Expand Down
8 changes: 7 additions & 1 deletion test/unit/entry-queryable.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,11 @@ describe('Query Operators API test cases', () => {
const query2: Query = await contentType.Entry().query().where('fieldUID', QueryOperation.EQUALS, 'value2');
const query = await contentType.Entry().query().or(query1, query2);
expect(query._parameters).toStrictEqual({ '$or': [ {'fieldUID': {'$in': ['value']}}, { 'fieldUID': 'value2' } ] });
});
});
it('should return entry when both conditions are matching - and', async () => {
const query1: Query = await contentType.Entry().query().containedIn('fieldUID', ['value']);
const query2: Query = await contentType.Entry().query().where('fieldUID', QueryOperation.EQUALS, 'value2');
const query = await contentType.Entry().query().and(query1, query2);
expect(query._parameters).toStrictEqual({ '$and': [ {'fieldUID': {'$in': ['value']}}, { 'fieldUID': 'value2' } ] });
});
});

0 comments on commit 82987b9

Please sign in to comment.