Skip to content

Commit

Permalink
Find plain records (#63)
Browse files Browse the repository at this point in the history
Closes #58.

- Add `plain` param to `findOne` and `findMany` to return the plain
properties.
  • Loading branch information
themetalfleece authored May 27, 2023
1 parent e1c1ea3 commit 8eecefc
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ const users = await Users.findMany({
skip: 3,
/* --> (optional) the order of this query, in this case by: age DESC, id ASC */
order: [['age', 'DESC'], ['id', 'ASC']],
/* --> (optional, default false) returns an array of the plain properties, instead of Instances */
plain: false,
/* --> (optional) throws NeogmaNotFoundError if no nodes are found (results length 0) */
throwIfNoneFound: true,
/* --> (optional) an existing session or transaction to use */
Expand All @@ -44,6 +46,8 @@ const user = await Users.findOne({
},
/* --> (optional) the order of this query, in this case by: id ASC */
order: [['id', 'ASC']],
/* --> (optional, default false) returns the plain properties, instead of Instance */
plain: false,
/* --> (optional) throws NeogmaNotFoundError if the node is not found */
throwIfNotFound: true,
/* --> (optional) an existing session or transaction to use */
Expand Down
100 changes: 99 additions & 1 deletion src/ModelOps/ModelOps.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ModelFactory, ModelRelatedNodesI, NeogmaInstance } from './ModelOps';
import * as dotenv from 'dotenv';
import { QueryRunner } from '../Queries/QueryRunner';
import { neo4jDriver, NeogmaModel } from '../index';
import { QueryBuilder } from '../Queries';
import { Op, QueryBuilder } from '../Queries';
import * as uuid from 'uuid';

const { getResultProperties } = QueryRunner;
Expand Down Expand Up @@ -606,6 +606,104 @@ describe('createMany', () => {
});
});

describe('findOne', () => {
it('finds one', async () => {
const user = await Users.createOne({
id: uuid.v4(),
name: 'user1',
});

const foundUser = await Users.findOne({
where: {
id: user.id,
},
});

expect(foundUser).toBeTruthy();
expect(foundUser?.id).toEqual(user.id);
expect(foundUser?.dataValues.id).toEqual(user.dataValues.id);
});

it('finds many plain', async () => {
const userData = {
id: uuid.v4(),
name: 'user1',
};
const user = await Users.createOne(userData);

const foundUser = await Users.findOne({
where: {
id: user.id,
},
plain: true,
});

expect(foundUser).toEqual(userData);
// @ts-expect-error -- dataValues is not defined on plain
foundUser.dataValues?.id;
});
});

describe('findMany', () => {
it('finds many', async () => {
const user1 = await Users.createOne({
id: uuid.v4(),
name: 'user1',
});

const user2 = await Users.createOne({
id: uuid.v4(),
name: 'user2',
});

const users = await Users.findMany({
where: {
id: {
[Op.in]: [user1.id, user2.id],
},
},
});

expect(users).toHaveLength(2);
expect(users[0].id).toEqual(user1.id);
expect(users[1].id).toEqual(user2.id);
expect(users[0].dataValues.id).toEqual(user1.dataValues.id);
expect(users[1].dataValues.id).toEqual(user2.dataValues.id);
});

it('finds many plain', async () => {
const user1Data = {
id: uuid.v4(),
name: 'user1',
};
const user1 = await Users.createOne(user1Data);

const user2Data = {
id: uuid.v4(),
name: 'user2',
};
const user2 = await Users.createOne(user2Data);

const users = await Users.findMany({
where: {
id: {
[Op.in]: [user1.id, user2.id],
},
},
plain: true,
});

expect(users).toHaveLength(2);
expect(users[0]).toEqual(user1Data);
expect(users[1]).toEqual(user2Data);
expect(users).toEqual([user1Data, user2Data]);
// @ts-expect-error -- dataValues is not defined on plain
users[0].dataValues?.id;
// @ts-expect-error
users[1].dataValues?.id;
});
});

describe('addRelationships', () => {
it('adds a relationship after the Model definition', async () => {
/* Orders */
Expand Down
34 changes: 23 additions & 11 deletions src/ModelOps/ModelOps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,26 +226,30 @@ interface NeogmaModelStaticsI<
where: WhereParamsI;
},
) => Promise<number>;
findMany: (
findMany: <Plain extends boolean = false>(
params?: GenericConfiguration & {
/** where params for the nodes of this Model */
where?: WhereParamsI;
limit?: number;
skip?: number;
order?: Array<[Extract<keyof Properties, string>, 'ASC' | 'DESC']>;
/** returns an array of the plain properties, instead of Instances */
plain?: Plain;
/** throws an error if no nodes are found (results length 0) */
throwIfNoneFound?: boolean;
},
) => Promise<Instance[]>;
findOne: (
) => Promise<Plain extends true ? Properties[] : Instance[]>;
findOne: <Plain extends boolean = false>(
params?: GenericConfiguration & {
/** where params for the nodes of this Model */
where?: WhereParamsI;
order?: Array<[Extract<keyof Properties, string>, 'ASC' | 'DESC']>;
/** returns the plain properties, instead of Instance */
plain?: Plain;
/** throws an error if the node is not found */
throwIfNotFound?: boolean;
},
) => Promise<Instance | null>;
) => Promise<(Plain extends true ? Properties : Instance) | null>;
createRelationship: (
params: CreateRelationshipParamsI & {
/** throws an error if the number of created relationships don't equal to this number */
Expand Down Expand Up @@ -1356,19 +1360,27 @@ export const ModelFactory = <

const res = await queryBuilder.run(queryRunner, params?.session);

const instances = res.records.map((record) => {
const instance = Model.buildFromRecord(record.get(rootIdentifier));
instance.__existsInDatabase = true;
return instance;
});
let returnData: Instance[] | Properties[] = [];

if (params?.plain) {
returnData = res.records.map(
(record) => record.get(rootIdentifier).properties,
);
} else {
returnData = res.records.map((record) => {
const instance = Model.buildFromRecord(record.get(rootIdentifier));
instance.__existsInDatabase = true;
return instance;
});
}

if (params?.throwIfNoneFound && !instances.length) {
if (params?.throwIfNoneFound && !returnData.length) {
throw new NeogmaNotFoundError(`No node was found`, {
label: Model.getLabel(),
});
}

return instances;
return returnData;
}

public static async findOne(
Expand Down

0 comments on commit 8eecefc

Please sign in to comment.