Sequelize Many-to-Many relationship but only create if exists - javascript

Objective:
Create a hashtagging system against a Product
Models:
Products
Hashtags
ProductTags (join table)
What I'm doing
When I create a new product the following happens:
Product is created
Hashtag is created
ProductTag join is created
The data looks like this:
{
"category_id":2,
"description":"Some description",
"price": 45,
"currency_id": "GBP",
"hashtags":[
{"tag":"tagnumber1"},
{"tag":"tagnumber2"},
{"tag":"tagnumber3"}
]
}
The Product.create code looks like this:
models.Product.create(data, {
include: [
{
model: models.Hashtag,
as: "hashtags",
attributes: models.Hashtag.fields
}
]
});
Issue
When I create the product for the first time with tag: tagnumber1, tagnumber2,tagnumber3. It adds these into the Hashtag table and creates the relation in the ProductTag table.
But when I create another product with the same tag: tagnumber1, tagnumber2,tagnumber3. It still adds these same tags into the Hashtag table.
How?
Is it possible on the second add to still have it INSERT into ProductTags but instead of duplicating the tags in Hashtag to grab the ids if they match?

Related

Sequelize and defaultScope with Models associated

I am using Sequelize with Express, and Node js and I am trying to define defaultScope for Models.
Card and Tag have a Many To Many association.
Here are Models definitions and addScope
// Models Associations
// ONE TO MANY
List.hasMany(Card, {
as: "cards",
});
Card.belongsTo(List, {
as: "list",
});
// MANY TO MANY
Card.belongsToMany(Tag, {
as: "tags",
through: "card_has_tag",
updatedAt: false,
});
Tag.belongsToMany(Card, {
as: "cards",
through: "card_has_tag",
updatedAt: false,
});
// SCOPES
Card.addScope("defaultScope", {
include: {
association: "tags",
},
});
List.addScope("defaultScope", {
include: {
association: "cards",
include: "tags",
},
});
// What I would like to implement
// If I comment lines below => List and Card queries are working
Tag.addScope("defaultScope", {
include: {
association: "cards",
},
});
I would like to print by default all related infos with associated relations.
I want to get this info when I execute a sequelize query for each model.
LISTS with associated :
cards
tags
CARDS with associated:
tags
TAGS with associated :
cards
I manage to get 1 & 2, but when I add Tag.addScopenothing is working anymore.
When I change defaultScope by another string by defining a scope all (for example) , and when I use model.scope("all").findAll(), this is working, but it is not what I would like to do becaue I want to use defaultScope to have a default behavior so I don't have to specify scope in queries command like (findAll...)
Is there a way I can do that ?
The way you are trying to set it up results in an endless recursion, you simply can't have it like that.
If you set it up like that and query Card it will include Tag which will include Card which will include Tag and so on until you get Maximum call stack size exceeded.
There is a workaround you can use, which is to add another scope which includes nothing, then specify that scope for the model in the defaultScope.
Tag.addScope("noInclude", {});
Card.addScope("noInclude", {});
Tag.addScope("defaultScope", {
include: [
{
model: Card.scope("noInclude"),
as: "cards"
}
]
});
Card.addScope("defaultScope", {
include: [
{
model: Tag.scope("noInclude"),
as: "cards"
}
]
});
This should give you the desired behaviour.

match field from multiple lookup in aggregate

I have a query for doing a lookup on two other collections, one contains information about students, other contains information about classes. The collection I'm running the query contains information about activities.
The things is: I can't compare a field from the second lookup I've done (on classes), for some reason the fields I add don't seem to work on the project field either.
Here's my query:
[
{"$lookup":{
"from":"students",
"localField":"class_id",
"foreignField":"classes_registered",
"as": "std"
}},
{"$unwind":"$std"},
{"$addFields":{"id_cls":{"$toString":"cls._id"},
"cls_name":"$$cls.name"
}},
{"$lookup":{
"from":"classes",
"localField":"class_id",
"foreignField":"id_cls",
"as": "cls"
}},
{"$unwind":"$std"},
{"$match":{
"$expr":{
"$and":[{
"$eq":["$std.email", filters["email"]]
},
{
"$eq":["$cls.name", filters["class_name"]]},
]
}
}
},
{"$project":{
"_id":0,
"cls.name":1,
"title":1,
"info":1,
"date_start":1,
"date_final":1,
"list":1
}}
]
"cls.name" shows always as "[ ]" on the response from query and
"$eq":["$cls.name", filters["class_name"]},
also doesn't compare to anything.
student collection sample:
{"_id":{"$oid":"60e3bfef0046de182072361d"},
"name":"matheus",
"date":{"$date":"2021-07-06T02:29:03.974Z"},
"email":"math#math",
"classes_registered":["60b4753f7976fb83300918f0","60b477557976fb83300918f2"]}
classes collection sample:
{"_id":{"$oid":"60b477557976fb83300918f2"},
"name":"desenho",
"teachers":["60b474937976fb83300918f1","60b474937976fb83300918ee"],
"date":{"$date":"2021-05-31T05:42:45.232Z"}}
classes_activities sample:
{"_id":{"$oid":"60e4c88ee19fb3797390b3f9"},
"title":"Trabalho Discente Efetivo II",
"info":"Desenhar em perspectiva cavallera a formiga apresentada em aula",
"date_start":{"$date":"2021-07-06T02:00:00.000Z"},
"date_final":{"$date":"2022-07-06T02:00:00.000Z"},
"list":1,
"class_id":"60b477557976fb83300918f2"}

How to display nested field mongodb in EJS

I am trying to display a field that contains a image link and that is nested in my collection in MongoDB to ejs. However when i try to display it EJS can't find the image.. I am using the User schema so when I write: <%=user.slot1img%> then it won't be able to find that resource.
The structure is like this for each item:
Inventory: [
{
Item1: [
{
slot1img: "",
slot1text: "",
}
],
So how could I show a item if its nested in mongodb to the EJS file?
use nested for loop
inventory.forEach(i => {
i.Item1.forEach(j => {
<%= j.slot1.img %>
})
})

Insert multiple records in single call

So I'm trying to insert an array of records of length to Azure Table. I'm on New Azure portal, and all the help I found was for old one.
New Azure Portal's Script page looks like
I've tried to override the insert method as following:
var table = require('azure-mobile-apps').table();
table.insert(function (context) {
all_answers = context.item.answers;
console.log(all_answers[0]);
return context.execute();
});
Log shows the following object:
{ id: '',
userid: '0029C048-B8A0-42AE-B8F8-2B9402D69EEF',
createdate: '2016-01-30 00:40:18',
questionid: 1,
choiceid: 0
}
How can I insert all records of array in Table?
Anticipated Thanks

Qml Nested List Model Append Data

I have my list mode
ListModel {
id: nestedModel
}
and I can append the list model using the code
nestedModel.append({
locationName: qsTr("Location5"),
collapsed: true,
folders: [{
folderName: qsTr("Cam11")
}, {
folderName: qsTr("Cam22")
}, {
folderName: qsTr("Cam33")
}, {
folderName: qsTr("Cam44")
}]
})
Which works fine.
But I need to append the inner list only using the same append model, like I have already Cam11,Cam22,Cam33,Cam44 in my list model, and I have to append Cam55,Cam66 dynamically.
How it’s possible?
Any help will be appreciated…
Thanks
Haris
Finally I found the answer here
We can append new data to child list using,
nestedModel.get(index).folders.append({"folderName": "Cam55"})
nestedModel.get(index).folders.append({"folderName": "Cam66"})

Categories

Resources