I have this query in sequelize:
Domicilio.hasMany(User, {foreignKey: 'UserId'});
const abonados = await Domicilio.findAll({include: User});
Which result is the following:
SELECT domicilio.DomicilioId, _users.UserId AS _users.UserId, _users.UserName AS _users.UserName, _users.FullName AS _users.FullName, _users.Password AS _users.Password, _users.Documento AS _users.Documento, _users.Cuit AS _users.Cuit, _users.Email AS _users.Email, _users.FechaBajada AS _users.FechaBajada, _users.FechaContrato AS _users.FechaContrato, _users.FechaNacimiento AS _users.FechaNacimiento, _users.Phone AS _users.Phone, _users.FailedPasswordCount AS _users.FailedPasswordCount, _users.IsActive AS _users.IsActive, _users.IsLocked AS
_users.IsLocked, _users.IsTestUser AS _users.IsTestUser, _users.LastLoginDate AS _users.LastLoginDate, _users.createdAt AS _users.createdAt, _users.createdBy AS _users.createdBy, _users.deletedAt AS _users.deletedAt, _users.deletedBy AS _users.deletedBy, _users.updatedAt AS _users.updatedAt, _users.updatedBy AS _users.updatedBy, _users.CondicionIVAId AS _users.CondicionIVAId, _users.OnuId AS _users.OnuId, _users.ServicioId AS _users.ServicioId FROM domicilio AS domicilio LEFT OUTER JOIN _user AS _users ON domicilio.DomicilioId = _users.UserId;
But I don't need the ALIAS of each of the columns of table _user. E.g _user.UserId I need only the name of each column without alias. Is there any way to aproach this?
There are some ways to change the value of the returning column
First I would suggest that you fetch only the columns really needed
by you at the model endpoint that way the response is concise.
Please refer the code below in which you can see how you can provide
alias in an association, the alias you provide in there is the one
which is used during the include you can fiddle around to get the
desired behavior. Also, you can tweak your findAll with option
params like {raw: true}
Official Docs:
https://sequelize.org/master/manual/assocs.html
https://sequelize.org/master/class/lib/model.js~Model.html#static-method-findAll
Ship.belongsTo(Captain, { as: 'leader' }); // This creates the `leaderId` foreign key in Ship.
// Eager Loading no longer works by passing the model to `include`:
console.log((await Ship.findAll({ include: Captain })).toJSON()); // Throws an error
// Instead, you have to pass the alias:
console.log((await Ship.findAll({ include: 'leader' })).toJSON());
// Or you can pass an object specifying the model and alias:
console.log((await Ship.findAll({
include: {
model: Captain,
as: 'leader'
}
})).toJSON());
Second but not very recommended way is to provide a raw query with
the parameter [Do not use javascript template string to pass the
args] here you have control over the params and conditions
Docs for raw query: https://sequelize.org/master/manual/raw-queries.html
Lastly, you can use alias in attribute to customize the value's key
to anything you like
const abonados = await Domicilio.findAll({
include: User,
attributes: [['UserId', 'newUserId'], ['UserName 'newUserName']]
});
P.S: literal might also come in handy at times.
Related
What I'm doing:
I'm reading csv which contains data like townships, religions and so on. In the csv, they are text values. But of course in my table in the database, they are foreign_key. So to insert those, I need to map those text values to id.
It is possible to get the id like below.
const { townshipId } = await models.Township.findOne({
where: { name: township },
attributes: ["townshipId"],
raw: true,
});
The problem:
But the problem what I think is that those findOne(s) will be populated in my entire method because I have like 50 other properties besides township.
What I'm trying
I'm trying to pass township-name to a getter method, expecting its equivalent townshipId.
I found out that it is possible to use getter and setter in sequelize. But I don't find how to pass parameters to those.
My question
Am I trying the correct way to import the csv data? How can I use getters (and setters) with parameters in sequelize?
Maybe if you want to exclude columns from the result, you pass the "attributes" field like:
attributes: { exclude: ['field1','field2'] }
This way you wont show the columns "field1" and "field2" in the result.
Can you please suggest how to get select fields from find method ?
e.g
let params = {
limit,
offset,
query: request
};
this.adapter.find(params)
Here, this will return all fields but instead of this I need only account_id from the resultset. I've already tried with fields inside params as well as settings{ fields: ["accout_id", "username"]} but doesn't work.
e.g
fields: ["account_id"]
Please guide me.
Thanks
Yes... I got the solution. I've used 'this.model' intead of 'this.adapter' like following way.
let params = {
limit,
offset,
query: request
};
this.model.find({
attributes: ['account_id'],
where : first_name : {
$like: '%Adam%'
}
})
Php:
$json_string = "{
"26":{"blabla":123,"group_id":1,"from":"27.08.2018","to":"02.09.2018"},
"25":{"blabla":124,"group_id":1,"from":"20.08.2018","to":"26.08.2018"},
"24":{"blabla":125,"group_id":1,"from":"20.08.2018","to":"26.08.2018"}
}"
my.blade.php template:
<my-component :records={{ $json_string }}></my-component>
MyComponent.vue:
export default {
props: ['records'],
...
mounted: function () {
console.log(this.records);
}
Output is:
{__ob__: Observer}
24:(...)
25:(...)
26:(...)
And when I use v-for, records in my table in wrong order (like in console.log output).
What I am doing wrong?
EDIT:
I figured out 1 thing:
When I do json_encode on collection where indexes are from 0 till x, than json string is: [{some data}, {some data}]
But if I do ->get()->keyBy('id') (laravel) and than json_encode, json string is:
{ "26":{some data}, "25":{some data}, "24":{some data} }
Then how I understood, issue is in different outer brackets.
In Javascript keys of objects have no order. If you need a specific order then use arrays.
Here is documentation for keyBy Laravel method: https://laravel.com/docs/5.6/collections#method-keyby
I wanted to have ids for rows data to fast and easy access without iterating over all rows and check if there is somewhere key Id which is equals with my particular Id.
Solution: not to use keyBy method in Laravel and pass json string to Vue component like following [{some data}, {some data}] (as I described in my Question Edit section) - this will remain array order as it used to be.
I found this short and elegant way how to do this, instead of writing js function by myself:
Its find() method: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
Example:
let row = records.find( record => record.id === idToFind );
Assuming I have the following MySQL tables to represent pricebooks, items and the relationship between them:
item - item_id|name|...etc
pricebook - pricebook_id|name|...etc
and the following pivot table
pricebook_item - pricebook_id|item_id|price|...etc
I have the correlating Eloquent models: Pricebook, Item and a repository named PricebookData to retrieve the necessary information.
Within the PricebookData repository, I need to get the pricebook data grouped by pricebook id and then keyed by item_id for easy access on client side.
If I do:
Pricebook::all()->groupBy('pricebook_id');
I get the information grouped by the pricebook_id but inside each pricebook the keys are simple numeric index (it arrives as js array) and not the actual product_id. So when returning to client side Javascript, the result arrives as the following:
pricebookData: {1: [{}, {}, {}...], 2: [{}, {}, {}...]}
The problem with the prices arriving as array, is that I can not access it easily without iterating the array. Ideally I would be able to receive it as:
pricebookData: {1: {1001:{}, 1002: {}, 1003: {}}, 2: {1001:{}, 1002: {}, 1003: {}}}
//where 1001, 1002, 1003 are actual item ids
//with this result format, I could simply do var price = pricebookData[1][1001]
I've also tried the following but without success:
Pricebook::all()->keyBy('item_id')->groupBy('pricebook_id');
The equivalent of what I am trying to avoid is:
$prices = Pricebook::all();
$priceData = [];
foreach ($prices as $price)
{
if (!isset($priceData[$price->pricebook_id]))
{
$priceData[$price->pricebook_id] = [];
}
$priceData[$price->pricebook_id][$price->item_id] = $price;
}
return $priceData;
I am trying to find a pure elegant Eloquent/Query Builder solution.
I think what you want is
Pricebook::all()
->groupBy('pricebook_id')
->map(function ($pb) { return $pb->keyBy('item_id'); });
You first group by Pricebook, then each Pricebook subset is keyed by item_id. You were on the right track with
Pricebook::all()->keyBy('item_id')->groupBy('pricebook_id');
unfortunately, as it is implemented, the groupBy resets previous keys.
Update:
Pricebook::all()->keyBy('item_id')->groupBy('pricebook_id', true);
(groupBy second parameter $preserveKeys)
This should be a fairly simple one.
myobject has various properties, _id, name, createdBy, date etc
In my find query I want to only return specific fields from within myObject. So for example, what would I need to do to modify the find query below so that only name was returned?
myCollection.find({createdBy: someId}, {fields: {myObject: 1}}).fetch();
Currently this will return everything in myObject which it should do, I just want one field within myObject returned.
Here is a way to do it within the query:
myCollection.find({createdBy: someId}, {fields: {'myObject.name':
1}}).fetch();
Note the quotes around
'myObject.name'
Lets assume we are talking about posts, and a post document looks like this:
{
_id: 'abc123',
title: 'All about meteor',
author: {
firstName: 'David',
lastName: 'Weldon'
}
}
You can then extract all of the last names from all of the authors with this:
var lastNames = Posts.find().map(function(post) {
return post.author.lastName;
});
Modify the selector and options as needed for your collection. Using fields in this case may be a small optimization if you are running this on the server and fetching the data directly from the DB.