I have a question how to build a custom api script that returns sub objects from related tables.
My table structure looks like this ( I'm not allowed to upload an Image :-( ).
My script looks like this (SQL is much much more complex, I make it short for my question):
exports.get = function(request, response) {
var sql = "SELECT * FROM [PointsOfInterests] ";
request.service.mssql.query(sql, [],{
success: function(results)
{
response.send(statusCodes.OK, results);
}
});
};
My question now is how to include the property "address" to the result?
My reslut object shoud look like this:
[
{
id: 123,
address:
{
City: test
}
}
]
Thanks for your help!
I understand that your question refers to Windows Azure Mobile Services.
You can do this using a custom API. See Define custom APIs in Windows Azure Mobile Services.
Use a SQL query that uses joints to return the data you need from both tables. See Join Fundamentals and Using Inner Joins to learn the syntax.
For instance, you could use a query such as:
select a.Id, a.Name, a.Location, b.City, b.PLZ, b.Street
from PointsOfInterest as a
inner join Address as b
on a.AddressId = b.ID
and then create a JavaScript object from the result set, with the structure your response message needs.
You might also need to use a left outer join if there are records in "a" which are not related to any records in "b" (optional relationship).
Related
Short Version: Is there an application in Node.js that offers functionalities similar to Python-SQLAlchemy's backref?
What I actually want to achieve:
I have three sql tables: article, chapter and subchapter. One article has multiple chapters, and on chapter can contain multiple or zero subchapter.
With SQLAlchemy it's quite simple, in models.py
class Article(db.Model):
...
chapters = db.relationship('Chapter', backref='mainArticle', lazy=True)
class Chapter(db.Model):
...
articleID = db.Column(db.Integer, db.ForeignKey('article.id'), nullable=False)
subChapters = db.relationship('subChapter', backref='mainChapter', lazy=True)
class subChapter(db.Model):
...
chapterID = db.Column(db.Integer, db.ForeignKey('chapter.id'), nullable=False)
And then I can access even the attributes of Article from subChapter:
subchapter = subChapter.query.first()
subchapter.mainChapter.id # Returns the chapter ID
subchapter.mainChapter.mainArticle.id # Returns the article ID
I've been using SQLAlchemy so I'm not sure how to select with SQLite, I tried:
app.get('/test/:articleID', (req, res) => {
let article_id = req.params.articleID;
let sql = `SELECT article.*, chapter.*, subchapter.*
FROM article
LEFT JOIN chapter ON article.id = chapter.articleID
LEFT JOIN subchapter ON chapter.id = subchapter.chapterID
WHERE article.id = ?`;
db.get(sql, [article_id], (err, article) => {
res.send(article)
});
})
But it just spit out a bunch of null...
Unfortunately current situation forces me to use Node.js instead of Python, so is there any way to achieve a similar result in Node.js?
Ok after some trials and errors I figured out a not-so-elegant way (maybe an ugly way) to get the job done without any third-party application.
First we select ALL the rows of the database that are linked to a article number with LEFT JOIN method. The null problem seems to be caused by identical key name in different tables (i.e. article.title, chapter.title, subchapter.title), so just distinguish them with AS method.
SELECT article.title,
chapter.title AS cT, chapter.chapterNumber AS cN,
subchapter.title AS scT, subchapter.subChapterNumber AS scN
FROM article
LEFT JOIN chapter ON article.id = chapter.articleID
LEFT JOIN subchapter ON chapter.id = subchapter.chapterID
WHERE article.id = 1
ORDER BY
chapterNumber ASC,
subChapterNumber ASC
This will get a bunch of entries where every subchapter is shown once, every chapter is shown at least once, depending on the subchapters it has.
Now we can write an iteration to sort the data. The fundamental idea is to form an article object, with a chapter property that contains an array of chapter objects, each one contains a subchapter property populated with an array of its own subchapter objects:
article = {
"title": "Article Title",
"chapters": [
{
"chapterNumber": 1,
"subchapters": [
{
"subchapterNumber": 1,
},
{
"subchapterNumber": 2,
}
]
},
{
"chapterNumber": 2,
"subchapters": []
},
]
}
Then we can simply use article.chapters[0] to access the chapter 1, and use article.chapters[0].subchapters[0] to get chapter 1.1.
To achieve this, the iteration to organise the data would be:
article = {"title":entries[0].title, "chapters":[]};
// First create all the chapter entries for subchapters to depend on.
for (i in entries) {
// Use underscore.js utility to determine if this chapter has already been put in.
if (_.findWhere(article.chapters, {"chapterNumber":entries[i].cN}) == null) {
// Create a new chapter entry.
article.chapters.push({"chapterNumber":entries[i].cN, "subchapters":[]})
}
};
// Then put in place all the subchapters.
for (i in entries) {
// Only analyse all the entries that contain a subchapter.
if (entries[i].scN){
// Find the corresponding chapter
chapter = _.findWhere(article.chapters, {"chapterNumber":entries[i].cN})
// Determine if this subchapter has already been put in.
if (_.findWhere(chapter.subchapters, {"subchapterNumber":entries[i].scN}) == null) {
// Create a new subchapter entry.
chapter.subchapters.push({"chapterNumber":entries[i].cN, "subchapterNumber":entries[i].scN})
}
}
};
The same principal still applies if the database is more complicated, like if every subchapter contains zero to multiple secondary subchapters.
Now a single article object contains all the informations we can possibly need to display an article in its order. A simple run with pug to display the schema would be:
html
head
title= article.title
body
each chapter in article.chapters
li= chapter.title
each subchapter in chapter.subchapters
li(style="padding-left:30px")= subchapter.title
This might not be quite efficient, but it at least get the job done. Please tell me if you know any better solution. Happy coding to everyone!
I made an SQL command line to select what the data I want but I can't find a way to do it with Sequelize.
I have two tables. One with some id linked to names and the other one with long texts.
I want to select all the text containing names from the id of the name.
This SQL command is working :
SELECT
texts.id,
texts.content
FROM
text
INNER JOIN users AS u ON u.id=38
WHERE
LOWER(texts.content) like concat('%',u.name,'%')
When I try to do it with Sequelize, I have something like this :
this.modelTexts.findAll({
include: [
{
model: this.modelUsers,
where: { id: 38 },
}
],
where: ...
})
When I try this, I have this error message :
SequelizeEagerLoadingError: users is not associated to texts!
I know I have to make something like :
Users.hasMany(Texts)
But I can't find a way to make it.
Thanks for taking a bit of your time for this request !
You can use Sequelize Raw for this, so your query can be something like this
sequelize.query(`
SELECT
texts.id,
texts.content
FROM
text
INNER JOIN users AS u ON u.id=38
WHERE
LOWER(texts.content) like concat('%',u.name,'%')`
{ type: sequelize.QueryTypes.SELECT});
Or you can add associations. So wherever in your code you have define models, add the following code
User.hasMany('Text', {foreignKey: 'user_id'});
NB: this solution was associated but if what you mean is no foreign keys on both tables
To solve this, here is what i would do
I Added this to my association first
models.User.hasMany(models.Text)
then also added this in my find query
Text.findAll({
attributes: ['id', 'content'],
include: [
{
model: users,
on: Sequelize.literal('users.id = 13')
},
],
});
While the above answer is great, I think it may defeat the whole purpose of using sequelize. Have you tried the following:
In your Text model definition:
Text.associate = models => {
Text.belongsTo(models.User)
}
In your User model definition:
User.associate = models => {
User.hasMany(models.Text)
}
Let me know if you're still having trouble! Understanding how sequelize works will save you many many hours in the long run! :)
I am developing an application using ASP.Net MVC and AngularJS. I am not familiar with linq and honestly I don't like it. But I am very familiar with SQL and I can perform complex queries. So, my question is, I want you to look at the below code from my MVC controller:
public JsonResult GetSupervisor()
{
var db = new scaleDBEntities();
return this.Json((from userObj in db.Users
select new
{
supervisorId = userObj.Id,
supervisorfName = userObj.usrFirstName,
supervisorlName = userObj.usrLastName,
})
, JsonRequestBehavior.AllowGet
);
}
How can I change the link query into SQL query?
I believe that I can do something like this:
var blogNames = db.Database.SqlQuery<string>("SELECT Name FROM dbo.Blogs").ToList();
So, if this is right, how can i use in in my return this.Json() for my angular?
Using the example you provided, something like this should work:
return this.Json(new {blogNames});
You're just creating an anonymously-typed object that the JSON serializer can use to produce an object like this:
{
"blogNames": ["blog one", "blog two"]
}
It'll be more complicated if you're trying to produce more complex results from a more complex query. But, well, that's what an ORM is for. I'd echo Gert Arnold's advice to embrace LINQ, rather than just deciding you don't like it because you're not used to it.
We are having som performance issue with EF and I want to try rewrite a query to inline sql. However I am having some difficulties, it is probably just a noob issue.
Lets say I have 3 classes: License, GroupLicense and Product
public class License
{
//stuff
Product MyProduct{get;set}
}
public class GroupLicense:License
{
// more stuff
}
public class Product
{
//product info stuff
}
Now I need to fetch some Grouplicenses depending on some requirements. However doing it with the datacontext and linq takes 2 minutes.
Something similar to this
var institutionLicenses = db.GroupLicenses
.Include(lic => lic.Product).Where(x => productIds.Contains(x.Product.Id) && x.LicenseStatus == StatusEnum.Active).ToList();
I want to do the same query using inline sql similar to this: I join the tables so all the primitive fields are okay.
var gl = db.Database.SqlQuery<GroupLicense>("select * from GroupLicense as g left join Licenses on g.Id =Licenses.Id").ToList();
(It is just example code - I know it is not working :))
However when executing, The base product property on License is null, all the primitive fields are there.
What do I need to change in my sql statement to make it work?
A user can create groups
A group had to have created by a user
A user can belong to multiple groups
A group can have multiple users
I have something like the following:
Parse.Cloud.afterSave('Group', function(request) {
var creator = request.user;
var group = request.object;
var wasGroupCreated = group.existed;
if(wasGroupCreated) {
var hasCreatedRelation = creator.relation('hasCreated');
hasCreatedRelation.add(group);
var isAMemberOfRelation = creator.relation('isMemberOf');
isAMemberOfRelation.add(group);
creator.save();
}
});
Now when I GET user/me with include=isMemberOf,hasCreated, it returns me the user object but with the following:
hasCreated: {
__type: "Relation"
className: "Group"
},
isMemberOf: {
__type: "Relation"
className: "Group"
}
I'd like to have the group objects included in say, 'hasCreated' and 'isMemberOf' arrays. How do I pull that using the REST API?
More in general though, am I approaching this the right way? Thoughts? Help is much appreciated!
First off, existed is a function that returns true or false (in your case the wasGroupCreated variable is always going to be a reference to the function and will tis always evaluate to true). It probably isn't going to return what you expect anyway if you were using it correctly.
I think what you want is the isNew() function, though I would test if this works in the Parse.Cloud.afterSave() method as I haven't tried it there.
As for the second part of your question, you seem to want to use your Relations like Arrays. If you used an array instead (and the size was small enough), then you could just include the Group objects in the query (add include parameter set to isMemberOf for example in your REST query).
If you do want to stick to Relations, realise that you'll need to read up more in the documentation. In particular you'll need to query the Group object using a where expression that has a $relatedTo pointer for the user. To query in this manner, you will probably need a members property on the Group that is a relation to Users.
Something like this in your REST query might work (replace the objectId with the right User of course):
where={"$relatedTo":{"object":{"__type":"Pointer","className":"_User","objectId":"8TOXdXf3tz"},"key":"members"}}