Skip to content

Commit

Permalink
feat(mongodb): Add support for list of references
Browse files Browse the repository at this point in the history
  • Loading branch information
marian2js authored and doug-martin committed Oct 16, 2020
1 parent 46db24a commit bc926a4
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 6 deletions.
20 changes: 15 additions & 5 deletions packages/query-typegoose/__tests__/__fixtures__/seeds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const TEST_ENTITIES: TestEntity[] = new Array(15)
dateType: new Date(`2020-02-${i}`),
numberType: i,
stringType: `foo${i}`,
testReferences: [],
});
});

Expand All @@ -22,14 +23,23 @@ export const TEST_REFERENCES: TestReference[] = [1, 2, 3, 4, 5].map((i) => {
});

export const seed = async (connection: Connection): Promise<void> => {
await connection.collection('testentities').insertMany(TEST_ENTITIES);
await connection.collection('testreferences').insertMany(TEST_REFERENCES);
const testEntitiesCollection = connection.collection('testentities');
const testReferencesCollection = connection.collection('testreferences');

await testEntitiesCollection.insertMany(TEST_ENTITIES);
await testReferencesCollection.insertMany(TEST_REFERENCES);

await Promise.all(
TEST_REFERENCES.map((testReference, i) => {
return connection
.collection('testentities')
.updateOne({ stringType: TEST_ENTITIES[i + 10].stringType }, { $set: { testReference: testReference.id } });
return testEntitiesCollection.updateOne(
{ stringType: TEST_ENTITIES[i + 10].stringType },
{ $set: { testReference: testReference.id } },
);
}),
);

await testEntitiesCollection.updateOne(
{ stringType: TEST_ENTITIES[TEST_ENTITIES.length - 1].stringType },
{ $set: { testReferences: TEST_REFERENCES.map((ref) => ref.id) } },
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ export class TestEntity {
@prop({ ref: TestReference })
testReference?: Ref<TestReference>;

@prop({ ref: TestReference })
testReferences?: Ref<TestReference>[];

getInputData(): Partial<TestEntity> {
return {
stringType: this.stringType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,4 +307,45 @@ describe('TypegooseQueryService', () => {
expect(queryResult.values().next().value).toBeUndefined();
});
});

describe('#queryRelations', () => {
let testEntity: TestEntity;

beforeEach(() => {
testEntity = plainToClass(TestEntity, {
...TEST_ENTITIES[0],
testReferences: TEST_REFERENCES.map((ref) => ref.id),
});
});

it('should return a map containing a list of references', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.queryRelations(TestReference, 'testReferences', testEntity, {});
expect(queryResult.values().next().value).toEqual(TEST_REFERENCES.map((ref) => ref.getOutputData()));
});

it('should apply a filter', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.queryRelations(TestReference, 'testReferences', testEntity, {
filter: { name: { eq: 'name2' } },
});
expect(queryResult.values().next().value).toEqual(TEST_REFERENCES.slice(1, 2).map((ref) => ref.getOutputData()));
});

it('should apply paging', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.queryRelations(TestReference, 'testReferences', testEntity, {
paging: { limit: 2, offset: 1 },
});
expect(queryResult.values().next().value).toEqual(TEST_REFERENCES.slice(1, 3).map((ref) => ref.getOutputData()));
});

it('should return an empty array if no results are found.', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.queryRelations(TestReference, 'testReferences', testEntity, {
filter: { name: { eq: 'does-not-exist' } },
});
expect(queryResult.values().next().value).toEqual([]);
});
});
});
28 changes: 27 additions & 1 deletion packages/query-typegoose/src/services/typegoose-query.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,33 @@ export class TypegooseQueryService<Entity> implements QueryService<Entity> {
dto: Entity | Entity[],
query: Query<Relation>,
): Promise<Relation[] | Map<Entity, Relation[]>> {
throw new Error('Not implemented yet');
const relationModel = this.Model.model(RelationClass.name) as ReturnModelType<new () => Relation>;
const relationQS = new TypegooseQueryService(relationModel, {
documentToObjectOptions: this.documentToObjectOptions,
});
const dtos: Entity[] = Array.isArray(dto) ? dto : [dto];
return dtos.reduce(async (prev, curr) => {
const map = await prev;
const ids = curr[relationName as keyof Entity];
if (Array.isArray(ids)) {
const relQuery = {
...query,
filter: {
...query.filter,
id: { in: ids },
},
} as Query<Relation>;
const entities = await relationQS.query(relQuery);
const sortedEntities = ids
.map((id: string) => {
const mongoDBKey = '_id' as keyof Relation; // eslint complains about keys starting with underscore
return entities.find((e) => ((e[mongoDBKey] as unknown) as string).toString() === id.toString());
})
.filter((e) => !!e);
map.set(curr, sortedEntities as Relation[]);
}
return map;
}, Promise.resolve(new Map<Entity, Relation[]>()));
}

removeRelation<Relation>(relationName: string, id: string | number, relationId: string | number): Promise<Entity> {
Expand Down

0 comments on commit bc926a4

Please sign in to comment.