Skip to content

Commit

Permalink
aggregation: Add automatic _id mapping in aggregation cursors #81
Browse files Browse the repository at this point in the history
  • Loading branch information
BenjD90 authored Oct 13, 2023
1 parent 55e2e8a commit b0adcfd
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 12 deletions.
25 changes: 17 additions & 8 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as fastDeepEqual from 'fast-deep-equal/es6';
import * as _ from 'lodash';
import * as mingo from 'mingo';
import {
AggregationCursor,
ClientSession,
Collection,
Db,
Expand Down Expand Up @@ -1062,16 +1063,24 @@ export class N9MongoDBClient<U extends BaseMongoObject, L extends BaseMongoObjec
options?: CollectionAggregationOptions,
readInOutputCollection: boolean = false,
): N9AggregationCursor<T> {
let nativeCursor: AggregationCursor;
let collection: Collection<U>;
if (readInOutputCollection) {
const nativeCursor = this.collection.aggregate<T>(aggregateSteps, options);
return new N9AggregationCursor<T>(this.collection, nativeCursor, aggregateSteps);
nativeCursor = this.collection.aggregate<T>(aggregateSteps, options);
collection = this.collection;
} else {
nativeCursor = this.collectionSourceForAggregation.aggregate<T>(aggregateSteps, options);
collection = this.collectionSourceForAggregation;
}
const nativeCursor = this.collectionSourceForAggregation.aggregate<T>(aggregateSteps, options);
return new N9AggregationCursor<T>(
this.collectionSourceForAggregation,
nativeCursor,
aggregateSteps,
);
return new N9AggregationCursor<T>(collection, nativeCursor, aggregateSteps).map((doc: T) => {
if (
typeof (doc as any)?._id === 'object' &&
(doc as any)._id.constructor.name === 'ObjectId' // faster than instanceof check
) {
(doc as any)._id = (doc as any)._id.toHexString();
}
return doc;
});
}

public aggregateWithBuilder<T = void>(
Expand Down
44 changes: 40 additions & 4 deletions test/aggregation-cursor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import test, { ExecutionContext } from 'ava';
import * as _ from 'lodash';

import { BaseMongoObject, N9AggregationCursor, N9MongoDBClient } from '../src';
import { ObjectId } from '../src/mongodb';
import { getBaseMongoClientSettings, getOneCollectionName, init, TestContext } from './fixtures';

class SampleType extends BaseMongoObject {
Expand Down Expand Up @@ -62,8 +61,7 @@ test('[Cursor] iterate using while hasNext ... next', async (t: ExecutionContext
items2.push(item);
}
t.is(items2.length, 5, 'cursor contains 5 items read with hasNext and next');
t.is(typeof items[0]._id, 'object', '_id is an object, aggregation results are not mapped');
t.true((items[0]._id as any) instanceof ObjectId, '_id is an ObjectId');
t.is(typeof items[0]._id, 'string', '_id is a string, aggregation results are mapped');

t.deepEqual(items2, items, 'compare two arrays');
});
Expand Down Expand Up @@ -119,7 +117,7 @@ test('[Cursor] Check cursor map function : should change data', async (t: Execut
.aggregate<SampleType>([{ $sort: { field1String: 1 } }])
.map((sampleType) => ({
// type of sampleType should be deduced automatically
_id: sampleType._id.toString(),
_id: sampleType._id,
somethingElse: sampleType.field1String,
}));
const items: { somethingElse: string; _id: string }[] = [];
Expand All @@ -140,6 +138,44 @@ test('[Cursor] Check cursor map function : should change data', async (t: Execut
}
});

test('[Cursor] Check _id automatic mapping, should leave objects', async (t: ExecutionContext<ContextContent>) => {
const cursor: N9AggregationCursor<{
_id: {
value: number;
prop2: number;
};
}> = t.context.mongoClient.aggregate<any>([
{
$group: {
_id: 1,
},
},
{
$project: {
_id: {
value: '$_id',
prop2: {
$sum: ['$_id', '$_id'],
},
},
},
},
]);

t.is(await cursor.count(), 1, 'check cursor length');
const doc = await cursor.next();
t.deepEqual(
doc,
{
_id: {
value: 1,
prop2: 2,
},
},
'_id is an object',
);
});

test('[Cursor] Check cursor map function : should be chainable', async (t: ExecutionContext<ContextContent>) => {
const cursor = t.context.mongoClient
.aggregate<SampleType>([{ $sort: { field1String: 1 } }])
Expand Down

0 comments on commit b0adcfd

Please sign in to comment.