feathers js get custom attribute value - javascript

I'm first time using feathers and Sequelize.
I want ask something for the example I have data user
name: 'user b',
email:'userb#mail.com',
createdAt:'2022-02-02',
updatedAt: '2022-02-02',
}
my expected return
name: 'user b',
email: 'userb#mail.com',
}
but I got all data user b

You can use the after hook to delete the properties that you don't want to get.
Or you can use the feathers.js common querying to deselect the specific fields and querying is the better approach.
Still, if you want to use the hooks, here is the code example:
after: {
get: [ (context) => {
delete context.result.data.fieldName;
}
}

Related

How to improve the performance of this MongoDB / Mongoose query?

I have a GET all products endpoint which is taking an extremely long time to return responses:
Product.find(find, function(err, _products) {
if (err) {
res.status(400).json({ error: err })
return
}
res.json({ data: _products })
}).sort( [['_id', -1]] ).populate([
{ path: 'colors', model: 'Color' },
{ path: 'size', model: 'Size' },
{ path: 'price', model: 'Price' }
]).lean()
This query is taking up to 4 seconds, despite there only being 60 documents in the products collection.
This query came from a previous developer, and I'm not so familiar with Mongoose.
What are the performance consequences of sort and populate? I assume populate is to blame here? I am not really sure what populate is doing, so I'm unclear how to either avoid it or index at a DB level to improve performance.
From the Mongoose docs, "Population is the process of automatically replacing the specified paths in the document with document(s) from other collection(s)"
So your ObjectId reference on your model gets replaced by an entire Mongoose document. Doing so on multiple paths in one query will therefore slow down your app. If you want to keep the same code structure, you can use select to specify what fields of the document that should be populated, i.e. { path: 'colors', model: 'Color', select: 'name' }. So instead of returning all the data of the Color document here, you just get the name.
You can also call cursor() to stream query results from MongoDB:
var cursor = Person.find().cursor();
cursor.on('data', function(doc) {
// Called once for every document
});
cursor.on('close', function() {
// Called when done
});
You can read more about the cursor function in the Mongoose documentation here.
In general, try to only use populate for specific tasks like getting the name of a color for only one product.
sort will not cause any major performance issues until you reach much larger databases.
Hope it helps!

RethinkDB - how to get a single document by query?

How can I get one document only by query in RethinkDB?
for an example, I want to get the document by this query below:
let searchQuery = {
name: 'rob'
}
var cursor = await r.table('users').filter(searchQuery).run(connection)
var user = await cursor.toArray()
console.log(user)
Result:
[ { email: 'fooz#bar.com',
id: '00e18124-714b-4298-aa34-5126ebda8828',
name: 'rob' } ]
Filter method actually returns a list of users with the same name - 'rob'.
I want the result like get method:
r.table('posts').get('a9849eef-7176-4411-935b-79a6e3c56a74').run(conn, callback);
Result:
{ email: 'fooz#bar.com',
id: '00e18124-714b-4298-aa34-5126ebda8828',
name: 'rob' }
But this method only takes document id.
Any ideas?
get (by id) fetches a single row selection by design, but filter is a streaming operation that processes multiple values (like arrays and streams). You might want to use nth that's designed to query for a stream/array element by its position, or its close alternative (). Here is an example:
.filter({ name: 'rob' })`
will return an array like
[{"email":"fooz#bar.com","id":"230de013-5d6a-436e-a7e9-a891c01913e5","name":"rob"}]
But the following queries
.filter({ name: 'rob' }).nth(0)
.filter({ name: 'rob' })(0)
will both return
{"email":"fooz#bar.com","id":"230de013-5d6a-436e-a7e9-a891c01913e5","name":"rob"}
Note that both also throw ReqlNonExistenceError: Index out of bounds: 0 in case if there are no rows found. However, you can easily fix it using the default operator:
.filter({ name: 'not-rob' }).nth(0).default(null)
Tested using RethinkDB data explorer with the "Raw view" tab active since both "Tree view" and "Table view" display single-element array as a single object. I'm almost sure the RethinkDB query engine is smart enough to make using nth(0) much more efficient rather than fetching the whole cursor to an array and taking the latter's first element in your code.

createRecord with custom ID in emberjs 2.x and Firebase 3.x

Until now, I saved all my data with the following line of code:
saveUser(params) {
let newUser = this.store.createRecord('user', params);
newUser.save();
this.transitionTo('index');
This worked fine, but didn't allow for custom ID's in firebase, so I changed it into:
saveUser(params) {
let newUser = this.store.createRecord('user', {
id: params.loginId,
name: params.name,
nickname: params.nickname,
imageUrl: params.imageUrl,
email: params.email
});
newUser.save();
this.transitionTo('index');
Processes them exactly as I want them to be stored on the Firebase database, so no problem there. I'm wondering though, and not finding any solution on the web, how I can combine the two, so that I don't have to bind every param. It's bound to give problems when I add/remove model properties.
Something I'm looking for would look like this (pseudo, yes I tried it, didn't work!):
let newUser = this.store.createRecord('user', {id: params.loginId}, params);
In short, I'm looking for the dynamic properties of ('model', params), but with the option to manually adjust 1 (or more) records without having to type out all of the params.
Thanks in advance !
You will probably want to customize your serializer to accomplish this. The example in the docs is a good one, so it should be pretty straightforward: https://guides.emberjs.com/v2.13.0/models/customizing-serializers/
I am, of course, assuming you are using Ember Data for your models.

Mongo/MongooseJS Object model doesn't save correctly [duplicate]

I'm using Mongoose ODM to partially validate models before they are stored to MongoDB.
Is it possible to relax Mongoose schemata so that a given part of the document is not validated? I have tried to the following:
var MySchema = new Schema({
user_id: { type: Schema.ObjectId, ref: 'User' },
freeform_data: {},
});
For instance if I set the contents to:
{
user_id: '123456',
freeform_data: {
dataitem1: 'a',
dataitem2: 'b',
items: [ 1, 2, 3, 4 ]
}
}
Then only user_id is stored, which makes perfectly sense security-wise.
How can I disable mongoose's validation for this field?
I am using this application only for prototyping purposes so I don't care about security right now (I just want to prototype).
When you modify the contents of a Mixed field like freeform_data, you need to notify Mongoose that you've changed its value by calling markModified(path) on the modified document or a subsequent save() call won't save it.
For example:
user.freeform_data = { foo: 'bar' };
user.markModified('freeform_data');
user.save();
Mongeese
: a mongoose multi-database helper/hack module
https://github.com/donpark/mongeese
Disclaimer: I was looking to connect to two MongoDB instances in the same app and gave up. So I haven't tried it.

Proper handling of API form input in express

I'm working on an API in express, and I wanted to ask if there's a better way to deal with user input. I use Express 4 and Sequelize, and use Sequelize for the validation. However, my creating route kinda looks like this:
app.route('/cards').post(requireAuthenticated, function (req, res, next) {
// Input validation
Card.create({
name: req.body.name,
caption: req.body.caption,
cost: req.body.cost,
tier: req.body.tier,
cardType: req.body.cardType,
readyTime: req.body.readyTime,
attack: req.body.attack,
health: req.body.health,
movement: req.body.movement,
range: req.body.range,
upkeep: req.body.upkeep,
canAttack: req.body.canAttack,
canDefend: req.body.canDefend,
canMove: req.body.canMove,
targetable: req.body.targetable,
description: req.body.description,
comment: req.body.comment,
user_id: req.user.id
})
.then( function (card) {
res.send(card);
})
.catch( function (e) { next(e); });
});
This works all right, but it leaves a lot to be desired. I omitted the validation of the input, because it's even longer, and this is not even the biggest model in my API.
One problem is obviously that whenever an attribute is not set, the attribute of the model will be set to null instead of default or old value. And then there's the problem of re-using this code.
I feel like I'm doing something wrong here, though. I tried to find an npm module on this, but only found ones for validation, not for proper putting input into the database.
Perhaps someone has a better, more elegant solution?
Regarding the lengthy creation of the record, you could use node's built-in extend function:
var extend = require('util')._extend
var newCard = extend({}, req.body);
newCard.user_id = req.user.id;
Card.create(newCard).then(...);
And it is possible for define defaults for columns using sequelize when you define your models:
sequelize.define('modelName', {
columnA: {
type: Sequelize.BOOLEAN,
defaultValue: true
}
...
});

Categories