Skip to content

Commit

Permalink
feat(schema): add support for filtering singular resource by indexed …
Browse files Browse the repository at this point in the history
…fields
  • Loading branch information
Peter Marton committed Jul 26, 2015
1 parent 22e3d36 commit b0d3032
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 18 deletions.
5 changes: 4 additions & 1 deletion example/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ var UserSchema = new mongoose.Schema({
name: {
type: String
},
age: Number,
age: {
type: Number,
index: true
},
createdAt: Date,
friends: [{
type: mongoose.Schema.Types.ObjectId,
Expand Down
46 changes: 38 additions & 8 deletions src/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {
GraphQLList
} from 'graphql/lib/type';

import mongoose from 'mongoose';

import {getProjection} from './utils';

/**
Expand Down Expand Up @@ -51,6 +53,28 @@ function getSchema (models) {
}, {});
});

// Model args
var modelArgs = reduce(modelMap, (modelArgs, model, modelName) => {
var args = reduce(model.schema.paths, (args, path) => {
var isIndexed = path.options && path.options.index === true;

if (isIndexed) {
args[path.path] = getField(path);
}

return args;
}, {});

args._id = {
name: '_id',
type: GraphQLString
};

modelArgs[modelName] = args;

return modelArgs;
}, {});

/**
* @method getField
* @param {Object} path
Expand Down Expand Up @@ -160,15 +184,21 @@ function getSchema (models) {
// TODO: args by index and _id
fields[singularName] = {
type: type,
args: {
_id: {
name: '_id',
type: new GraphQLNonNull(GraphQLString)
}
},
resolve: (root, {_id}, source, fieldASTs) => {
args: modelArgs[typeName],
resolve: (root, args, source, fieldASTs) => {
var projections = getProjection(fieldASTs);
return modelMap[typeName].findById(_id, projections);

args = reduce(args, (args, arg, argName) => {
if (arg && argName === '_id') {
args[argName] = mongoose.Types.ObjectId(arg);
} else if (arg) {
args[argName] = arg;
}

return args;
}, {});

return modelMap[typeName].findOne(args, projections);
}
};

Expand Down
54 changes: 45 additions & 9 deletions src/schema.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ describe('schema', () => {
name: {
type: String
},
age: Number,
age: {
type: Number,
index: true
},
weight: Number, // to test "floatish" numbers
createdAt: Date,
removed: Boolean,
Expand All @@ -39,15 +42,17 @@ describe('schema', () => {
it('should get data by id with selected fields', function* () {
var user = new User();

var findByIdStub = this.sandbox.stub(User, 'findById').returnsWithResolve(user);
var findByIdStub = this.sandbox.stub(User, 'findOne').returnsWithResolve(user);

var result = yield graphql(schema, `{
user(_id: "${user._id}") {
_id
}
}`);

expect(findByIdStub).to.calledWith(user._id.toString(), {
expect(findByIdStub).to.calledWith({
_id: user._id
}, {
_id: 1
});

Expand All @@ -60,8 +65,37 @@ describe('schema', () => {
});
});

// TODO: missing test cases
it('should get data by indexed fields');
it('should get data by indexed fields', function* () {
var user = new User({
name: 'Foo',
age: 24
});

var findByIdStub = this.sandbox.stub(User, 'findOne').returnsWithResolve(user);

var result = yield graphql(schema, `{
user(age: 24) {
name
age
}
}`);

expect(findByIdStub).to.calledWith({
age: 24
}, {
name: 1,
age: 1
});

expect(result).to.be.eql({
data: {
user: {
name: 'Foo',
age: 24
}
}
});
});

it('should get data with primitive fields', function* () {
var user = new User({
Expand All @@ -72,7 +106,7 @@ describe('schema', () => {
createdAt: new Date(1437911686190)
});

this.sandbox.stub(User, 'findById').returnsWithResolve(user);
this.sandbox.stub(User, 'findOne').returnsWithResolve(user);

var result = yield graphql(schema, `{
user(_id: "${user._id}") {
Expand Down Expand Up @@ -105,7 +139,7 @@ describe('schema', () => {
dates: [new Date(1437911686190), new Date(1437911680190)]
});

this.sandbox.stub(User, 'findById').returnsWithResolve(user);
this.sandbox.stub(User, 'findOne').returnsWithResolve(user);

var result = yield graphql(schema, `{
user(_id: "${user._id}") {
Expand Down Expand Up @@ -141,7 +175,7 @@ describe('schema', () => {
friends: [user1._id]
});

var findByIdStub = this.sandbox.stub(User, 'findById').returnsWithResolve(user2);
var findByIdStub = this.sandbox.stub(User, 'findOne').returnsWithResolve(user2);
var findStub = this.sandbox.stub(User, 'find').returnsWithResolve([user1]);

var result = yield graphql(schema, `{
Expand All @@ -153,7 +187,9 @@ describe('schema', () => {
}
}`);

expect(findByIdStub).to.calledWith(user2._id.toString(), {
expect(findByIdStub).to.calledWith({
_id: user2._id
}, {
name: 1,
friends: 1
});
Expand Down

0 comments on commit b0d3032

Please sign in to comment.