Whenever I do a findAll or findOne on a model and it involves nested association. All the property of the association also get nested. Like below :
ProductQCStatus.findAll({
include:[
{
model:Product,
include:{
model:ProductImage
},
attributes:["product_name","product_description","category"]
}
],
})
It will be below result
[{
//fields from ProductQCStatus table
Product:{
product_name: value
product_description: value,
...
ProductImage:{
images:[]
}
},
{
//fields from ProductQCStatus table
Product:{
product_name: value
product_description: value,
...
ProductImage:{
images:[]
}
}
......
]
I want the result not be nested but just one object with all the attributes defined inside nested associations.
I have already tried map(), also using other functions through which I can iterate and get the desired fields. But in that case, I have to traverse whole objects. I don't want that.I went through documentation, and I couldn't find anything there.
I wonder if there is any native method in sequelize itself to achieve this.
Related
I have red the documentation of sequelize but could not get the idea/concept i wanted ,I don't want just one attribute to be shown.
We have the following syntax to get the attributes we need
Model.findAll({
attributes:['foo','bar]
})
In my case I have many attributes in single table , I just want to hide one attribute.Is there any way in sequelize that we define the attribute which we don't want to see and get all other by default..
For Example....
Model.findAll({
attributes:hide foo , show all other attributes
})
AnyOne Can help..
You can use below syntax.
Model.findAll({
attributes: {
exclude: ['foo'] // hide this
}
});
You can also exclude fields on model level by adding in their default scope like below.
const Model = sequelize.define('model',{
secretColumn: Sequelize.STRING,
//... and other columns
}, {
defaultScope: {
attributes: { exclude: ['secretColumn'] }
}
});
I've got an apollo schema like this one:
type Batch {
Batch: String,
ItemCode: String,
PV: String,
ExpirationDate: DateTime,
Freezed: Boolean,
Item:Item,
Quantity: Float,
Fefo: Boolean
}
and a query in sequelize like that:
await models.Batch.findAll({
attributes: ['ItemCode','Lotto','ExpirationDate','Freezed', [Sequelize.literal(`CASE WHEN "Batch" ='${Batch}' THEN true ELSE false END`), "Fefo"] ],
where: whereClause,
include: [models.Item],
order: [
// Will escape title and validate DESC against a list of valid direction parameters
['ExpirationDate']
]
// attributes: models.mapAttribute(models.Batches, info)
})
returning an array of Batch objects.
All runs without problems, graphql query works well:
{
getFefoBatches (ItemCode:"200200201",Batch:"20201118B")
{
Batch, ExpirationDate, Fefo, Item { ItemCode ItemName }
}
}
but the "Fefo" field is not valorized with the "sequelize.literal" value. It's always null.
Maybe I don't known the proper syntax, but I tried everything possible, and also I searched for a solution but without success.
How is it possible to make a correct mapping between sequelize field and Apollo server schema?
Thanks in advance.
Okay, I discovered that the problem is not on sequelize query or on Apollo gql schema but is related to the model.
I added a virtual field on model with the same name of my query/schema field and everything works fine.
Very new to Mongoose -- I'm working on an existing project and have been given the task of changing some model properties. I understand that if a model contains a property of this type
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
this property references another model/schema, and to get access to that linked model/schema one needs to populate it to gain access to this property.
But in the code I'm reviewing (which I didn't write) there are many properties of this type
contentTypes: [{ ref: 'ContentType' }],
source: { ref: 'Source',required: true },
where another schema is referenced, but there is no type. Is this the same sort of relationship, and the id is implied? Is this a subdocument?
As an additional question: if in a model I wanted to refer to a property of a linked model (or schema), would I need to populate first? That is, if it's a subdocument, I can just use dot notation, but if it is a "linked" document, I'm not sure.
The answer was that the model schemas do not stand on their own, but are passed to a model "factory", which gives them the property types they need.
Thus from that factory the following snippet (below). I looked into the documentation for mongoose-autopopulateand I don't see what autopopulate=truemeans.
new: function(name, properties, statics, methods, schemaMods) {
// Add default definition to properties with references and load reference schemas
Object.keys(properties).forEach(function(key) {
var modifiedProperty = (property) => {
if (property.ref) {
property.autopopulate = true;
property.type = mongoose.Schema.Types.ObjectId;
}
return property;
};
if (Array.isArray(properties[key]) && properties[key].length === 1) {
properties[key][0] = modifiedProperty(properties[key][0]);
} else {
properties[key] = modifiedProperty(properties[key]);
}
});
I have a Schema:
var ProjectSchema = new Schema({
name: {
type: String,
default: ''
},
topics: [{
type: Schema.ObjectId,
ref: 'Topic'
}],
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
What I want to do is get an array with all topics from all projects. I cannot query Topic directly and get a full list because some topics are unassigned and they do not hold a reference back to a Project (for reasons of avoiding two way references). So I need to query Project and aggregate some how. I am doing something like:
Project.aggregate([{$project:{topics:1}}]);
But this is giving me an array of Project objects with the topics field. What I want is an array with topic objects.
How can I do this?
When dealing with arrays you typically want to use $unwind on the array members first and then $group to find the distinct entries:
Project.aggregate(
[
{ "$unwind": "$topics" },
{ "$group": { "_id": "$topics._id" } }
],
function(err,docs) {
}
)
But for this case, it is probably simplier to just use .distinct() which will do the same as above, but with just an array of results rather than documents:
Project.distinct("topics._id",function(err,topics) {
});
But wait there a minute because I know what you are really asking here. It's not the _id values you want but your Topic data has a property on it like "name".
Since your items are "referenced" and in another collection, you cannot do an aggregation pipeline or .distinct() operation on the property of a document in another collection. Put basically "MongoDB does not perform Joins" and mongoose .populate() is not a join, just something that "emulates" that with additional query(ies).
But you can of course just find the "distinct" values from "Project" and then fetch the information from "Topic". As in:
Project.distinct("topics._id",function(err,topics) {
Topic.find({ "_id": { "$in": topics } },function(err,topics) {
});
});
Which is handy because the .distinct() function already returned an array suitable for use with $in.
I'm playing with model associations in sails and I'm curious if it's possible to make a query base on the associated field.
Example:
User.js
attributes:{
classes: { collection: 'Class', via: 'students' }
}
Class.js
attributes: {
type: ...
students: { collection: 'User', via: 'classes'}
}
Is there a way to retrieve specific Classes of a Student base on the type of class because right now everything is being returned when I use .populate(). (maybe similar with the logic below)
User
.findOne({name: 'StudentA'})
.populate('classes')
.where({'classes.type':['type1', 'type2']})
.then(....)
Thanks
You can add a where clause to your populate like so:
User
.findOne({name: 'StudentA'})
.populate('classes', {where: {type: ['type1', 'type2']}})
.exec(...)
In addition to where, you can also use skip, limit and sort in the second argument to populate.
Keep in mind this is still (as of this posting) in beta, so if you find any issues where it seems to not be working correctly, please post them to the Waterline GitHub issues forum.