Removing an object from an array inside a Collection - arrays

I'm using the following methods to push and pull objects into the "following" array, which is a property on each user's profile.
Meteor.users.update({ _id: this.userId }, { $push: {
"profile.following": { _id: _id, service: service, type: type }}
});
// I specify that it is required to match these two properties to remove an object
Meteor.users.update({ _id: this.userId }, { $pull: {
"profile.following": { service: service, type: type } }
});
This approach does work, it removes the object, but I always get this error:
Exception while simulating the effect of invoking 'unfollow' Error: documentMatches needs a document {stack: (...), message: "documentMatches needs a document"} Error: documentMatches needs a document
at Error (native)
at _.extend.documentMatches (http://localhost:3000/packages/minimongo.js?e8806aa7782b729b2517ebc0cd10b321667f1427:1341:13)
at MODIFIERS.$pull (http://localhost:3000/packages/minimongo.js?e8806aa7782b729b2517ebc0cd10b321667f1427:3414:24)
at http://localhost:3000/packages/minimongo.js?e8806aa7782b729b2517ebc0cd10b321667f1427:3124:9
at Function._.each._.forEach (http://localhost:3000/packages/underscore.js?0a80a8623e1b40b5df5a05582f288ddd586eaa18:164:22)
at http://localhost:3000/packages/minimongo.js?e8806aa7782b729b2517ebc0cd10b321667f1427:3105:9
at Function._.each._.forEach (http://localhost:3000/packages/underscore.js?0a80a8623e1b40b5df5a05582f288ddd586eaa18:164:22)
at Function.LocalCollection._modify (http://localhost:3000/packages/minimongo.js?e8806aa7782b729b2517ebc0cd10b321667f1427:3098:7)
at LocalCollection._modifyAndNotify (http://localhost:3000/packages/minimongo.js?e8806aa7782b729b2517ebc0cd10b321667f1427:848:19)
at http://localhost:3000/packages/minimongo.js?e8806aa7782b729b2517ebc0cd10b321667f1427:765:12
I'm not sure if this is a bug with Meteor or if I maybe I'm not writing the query correctly.

Apparent $elemMatch is needed to do this:
Meteor.users.update({ _id: this.userId }, { $pull: {
"profile.following": { $elemMatch: { service: service, type: type } } }
});

Related

Use an array as response model in AWS Gateway cdk

I'm trying to create a typescript aws cdk to build up an API Gateway with this own swagger documentation.
There is one simple endpoint returning a list of "Supplier", but we don't know how to specify this in the cdk.
Here the code:
export function CreateSupplierMethods(apigw: apigateway.Resource,restApiId: string, scope: cdk.Construct, api: apigateway.RestApi) {
let suppliers = apigw.addResource('suppliers')
let supplierModel = new apigateway.Model(scope, "supplier-model", {
modelName: "supplier",
restApi: api,
contentType: 'application/json',
schema: {
description: "Supplier data",
title: "Supplier",
properties: {
code: { type: apigateway.JsonSchemaType.STRING, minLength: 4, maxLength: 6},
name: { type: apigateway.JsonSchemaType.STRING, maxLength: 81},
}
},
})
let getSuppliers = suppliers.addMethod('GET', new apigateway.MockIntegration(), {
methodResponses: [{
statusCode: "200",
responseModels: {
"application/json": supplierModel,
}
},
{
statusCode: "401",
}]
})
}
As you can see, the GET has the supplierModel as output.
How can I say "returns a list of supplierModel"? I wish I can use this model for both list of supplier and single instances of supplier (like a GET method with id as input).
Is this possible? If yes, how?
Looking the generated json, I'm trying to have something like this:
But what I'm getting now is quite different:
How can I get a result like the first image?
You are creating a model and assigning it to the method.
Create an array of those models and then assign that array to the method.
let supplierModelArray = new apigateway.Model(scope, "supplier-model-array", {
modelName: "supplier-array",
restApi: api,
contentType: 'application/json',
schema: {
description: "Supplier data",
title: "Supplier",
type: apigateway.JsonSchemaType.ARRAY
items: {type: supplierModel}
},
})
And change the "application/json": supplierModel in api to "application/json": supplierModelArray

How to use custom field in react admin, insted of { data: [...] }

I'm new in react-admin and I'm trying to create a new admin panel for my old API.
So when my data provider do API calls it causes me this error:
The response to 'getList' must be like { data : [...] }, but the received data is not an array. The dataProvider is probably wrong for 'getList'
The responses of my old API has various data fields like { 'posts': [] } or { 'users': [] }. How can I use these name of fields instead of { 'data': [] } ?
The 'data' in this case just refers to the type of information that should be retuned, not the name of the object.
Within your API, you can simply return a list in the following form:
const posts = [
{
"id":1,
"name":"post1"
},
{
"id":2,
"name":"post2"
},
];
return JSON.stringify(posts);
Then return that 'posts' object in your response and don't forget to set the expected ContentRange headers.
Not sure what language you are using, but the principle above should be easy enough to follow and apply in any language.

Creating a record with an n:m relationship, using Sequelize, NodeJS, and AngularJS

Update: I've gotten a fair bit further. Please see the bottom of the post...
I'm working on a project that is based on the sql-fullstack yeoman generator, and have been using the included example code as a guide. Things have progressed smoothly, for the most part, but I'm now in a scenario where I have two tables/models with a bidirectional n:m relationship:
TaskGroup:
module.exports = function(sequelize, DataTypes) {
var TaskGroup = sequelize.define("TaskGroup", {
taskGroupID: {
field: "TaskGroupID",
type: DataTypes.INTEGER,
allowNull: false,
unique: true,
autoIncrement: true,
primaryKey: true
},
name: {
field: "Name",
type: DataTypes.STRING,
allowNull: false
},
description: {
field: "Description",
type: DataTypes.STRING
},
modifiedBy: {
field: "ModifiedBy",
type: DataTypes.STRING
}
});
and Task:
module.exports = function(sequelize, DataTypes) {
var Task = sequelize.define("Task", {
taskID: {
field: "TaskID",
type: DataTypes.INTEGER,
allowNull: false,
unique: true,
autoIncrement: true,
primaryKey: true
},
name: {
field: "Name",
type: DataTypes.STRING,
allowNull: false
},
description: {
field: "Description",
type: DataTypes.STRING
},
isOnRunsheet: {
field: "IsOnRunsheet",
type: DataTypes.BOOLEAN
},
modifiedBy: {
field: "ModifiedBy",
type: DataTypes.STRING
}
});
Relationships:
// Tasks can belong to more than one group, and groups can belong to more than one task
db['TaskGroup'].belongsToMany(db['Task'], {as: 'Tasks', through: 'TaskGrouping'});
db['Task'].belongsToMany(db['TaskGroup'], {as: 'TaskGroups', through: 'TaskGrouping'});
On the client side, the user is able to create a new task and specify the associated task groups through a multiple select list. When the task is saved, I have both the task fields and an array of the associated task groups. A post is made with the request body containing this information, so that the server can create the task record.
Unfortunately, I can't seem to get the record created. I've been through a number of iterations, and I'm at the point where I get what appears to be a reasonable exception - I'm just stumped as to what the "reasonable" thing to do is...
Exception:
Unhandled rejection SequelizeDatabaseError: Cannot insert the value NULL into column 'TaskTaskID', table 'HelpCard
.dbo.TaskGrouping'; column does not allow nulls. INSERT fails.
at Query.formatError (C:\Projects\helpcard2\node_modules\sequelize\lib\dialects\mssql\query.js:215:10)
at Request.userCallback (C:\Projects\helpcard2\node_modules\sequelize\lib\dialects\mssql\query.js:66:25)
at Request.callback (C:\Projects\node_modules\tedious\lib\request.js:33:27)
at Connection.message (C:\Projects\node_modules\tedious\lib\connection.js:1179:27)
at Connection.dispatchEvent (C:\Projects\node_modules\tedious\lib\connection.js:519:45)
at MessageIO.<anonymous> (C:\Projects\node_modules\tedious\lib\connection.js:439:23)
at emitNone (events.js:67:13)
at MessageIO.emit (events.js:166:7)
at ReadablePacketStream.<anonymous> (C:\Projects\node_modules\tedious\lib\message-io.js:92:15)
at emitOne (events.js:77:13)
...
Here's the code on the client side:
$scope.createTask = function() {
if($scope.newTask === '') {
return;
}
$scope.newTask.modifiedBy = 'tkturney';
var taskBundle = {
task: $scope.newTask,
taskGroups: $scope.selectedGroups
};
$http.post('/api/tasks', taskBundle);
setTimeout(function() {
$scope.currentTask = $scope.newTask;
$scope.newTask = '';
$scope.addingTask = false;
refreshTasks();
}, 250);
};
...and on the server side:
exports.create = function(req, res) {
var task = Task(req).build(req.body.task);
task.setTaskGroups(req.body.taskGroups);
task
.save()
.then(function() {
return res.status(201).json(task);
})
.catch(function (err){
if(err) { return handleError(res, err); }
});
};
I'm sure that I'm missing something obvious, but the documentation that I've found has been pretty light on a scenario like this. I would appreciate any guidance; I'm just getting into sequelize, and I feel that there are times that I may have bitten off more than I can chew... :)
Update: After taking a closer look at the SQL, I discovered that the exception was being thrown when trying to insert into the join table (TaskGroupings). It was trying to insert a NULL for the task's primary ID, which is generally not a good thing. Looking at the code, I realized that I was trying to add the association before I had saved the record, leaving me with no PK. Moving the task.addTaskGroups() after the save() took care of that issue.
However, I also realized that I was passing an array of TaskGroup objects to the 'addTaskGroup()` call, instead of the actual IDs. So, I modified the client-side controller like so:
$scope.createTask = function() {
if($scope.newTask === '') {
return;
}
$scope.groupKeys = [];
angular.forEach($scope.selectedGroups, function(taskGroup) {
$scope.groupKeys.push(taskGroup.taskGroupID);
});
$scope.newTask.modifiedBy = 'tkturney';
var taskBundle = {
task: $scope.newTask,
taskGroups: $scope.groupKeys
};
$http.post('/api/tasks', taskBundle);
...
When I look at the debugger, I can see everything in the taskGroup object, but taskGroup.taskGroupID is coming back as undefined, so I'm still getting an exception because I'm not passing the PKs for the other side of the association.
Does anything leap out as to what might be screwy with this code fragment?
Ok, by changing the server-side controller from this:
exports.create = function(req, res) {
var task = Task(req).build(req.body.task);
task.setTaskGroups(req.body.taskGroups);
task
.save()
.then(function() {
return res.status(201).json(task);
})
.catch(function (err){
if(err) { return handleError(res, err); }
});
};
To this:
exports.create = function(req, res) {
var task = Task(req).build(req.body.task);
task
.save()
.then(function() {
task.setTaskGroups(req.body.taskGroups);
return res.status(201).json(task);
})
.catch(function (err){
if(err) { return handleError(res, err); }
});
};
That particular exception went away. The thing that I was missing (though it was staring me in the face) was the fact that there are two separate inserts happening - one for the task, and one for the association. I was thinking that I needed to set the association before saving the task, not realizing that setting that association caused another insert.
I still need to figure out why the PKs for the other side of the association aren't getting populated, but that's outside the scope of the original question...

Posting Schema.Types.ObjectId arrays to MongoDB

How can I post an array of Schema.Types.ObjectId (s) to MongoDB? I'm trying to create User Groups, which is a group of the 'User' Model e.g.
var UserGroup = new Schema({
users: [{
type: Schema.Types.ObjectId,
ref: 'User'
}]
});
New UserGroup Function
module.exports.create = function(request, response) {
var group = new UserGroup({
users = request.body.users
});
group.save(function(error) {
if(error) { throw error; } else { response.send('Group Created Successfully.');
});
};
I'm currently using Postman to test the functionality, how exactly should the data be posted?
As a Javascript array i.e ['A_USER_ID', 'A_USER_ID'] ?
Thanks!
#Answer
I was using the older syntax of the select() function, and therefore was passing invalid parameters to the $push function. When sending the request, I simply pass the ObjectIds as id,id,id and once they get to the server, simply put it into an array using var my_array = request.body.users.split(','); and then push it to the database using the following:
$push: { users: { $each: my_array } }
I hope this was helpful, the documentation isn't particularly clear on this matter.

RelayJS Invariant Violation with integer query parameter

I'm relatively new to Relay, so this may be an easy mistake I've made but I've been looking for some time already and I haven't found any information about the problem I'm having.
This is the error that I get from my application:
Uncaught Error: Invariant Violation: GraphQLFragmentPointer: Value for the argument to story on query Route should be a string, but it was set to 10. Check that the value is a string.
The problem is I actually want it to be 10 and don't want it to be string. Have I configured something incorrectly?
This is my GraphQL Schema:
var queryType = new GraphQLObjectType({
name: 'Query',
fields: () => ({
node: nodeField,
story: {
type: storyType,
args: {
storyID: {
description: 'Story ID',
type: GraphQLInt
}
},
resolve: (root, {storyID}) => {
if (storyID) {
return Story.get(storyID)
} else {
return Story.get(10)
}
}
},
}),
});
This is the relay route I've defined:
export default class extends Relay.Route {
static queries = {
story: () => Relay.QL`
query {
story(storyID: $storyID)
}
`,
};
static paramDefinitions = {
storyID: {
required: false
},
};
static routeName = 'StoryRoute';
};
And this is how I instantiate it:
let route = new Route({storyID: 10})
Ok, it looks like I've figured it out finally.
It appears that root fields are severely limited and can currently only have no parameters, a single string parameter or a multiple string parameters, connected straight with IDs of objects fetched.
Look for more information here: https://github.com/facebook/relay/issues/112
and here: https://github.com/facebook/relay/issues/94

Resources