Как добиться backref-подобного запроса в Node.js и sqlite? - PullRequest
0 голосов
/ 29 марта 2019

Короткая версия: Есть ли приложение в Node.js, которое предлагает функциональные возможности, аналогичные backref Python-SQLAlchemy?

Чего я действительно хочу достичь: у меня есть три таблицы sql: статья, глава и подраздел.Одна статья состоит из нескольких глав, а глава может содержать несколько или ноль подразделов.С SQLAlchemy это довольно просто, в 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)

И тогда я могу получить доступ даже к атрибутам Article из subChapter:

subchapter = subChapter.query.first()
subchapter.mainChapter.id # Returns the chapter ID
subchapter.mainChapter.mainArticle.id # Returns the article ID

Я использую SQLAlchemy, поэтому я 'я не уверен, как выбрать с SQLite, я попытался:

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)
    });
})

Но он просто выплевывает кучу нулей ...

К сожалению, текущая ситуация вынуждает меня использовать Node.js вместоPython, есть ли способ достичь аналогичного результата в Node.js?

1 Ответ

0 голосов
/ 30 марта 2019

Хорошо, после некоторых проб и ошибок я нашел не очень элегантный способ (возможно, уродливый), чтобы выполнить работу без стороннего приложения.Сначала мы выбираем ВСЕ строки базы данных, связанные с номером статьи, методом LEFT JOIN.Кажется, проблема null вызвана одинаковыми именами ключей в разных таблицах (т. Е. article.title, chapter.title, subchapter.title), поэтому просто различайте их с помощью метода AS.

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

Это позволит получить кучу записей где каждая подглава показывается один раз, каждая глава показывается как минимум один раз, в зависимости от того, какая подглава имеет .

Теперь мы можем написать итерацию для сортировки данных.Основная идея состоит в том, чтобы сформировать объект article со свойством chapter, которое содержит массив объектов главы, каждый из которых содержит свойство subchapter, заполненное массивом своих собственных объектов подглавы:

article = {
    "title": "Article Title",
    "chapters": [
        {
            "chapterNumber": 1,
            "subchapters": [
                {
                    "subchapterNumber": 1,
                },
                {
                    "subchapterNumber": 2,
                }
            ]
        },
        {
            "chapterNumber": 2,
            "subchapters": []
        },
    ]
}

Тогда мы можем просто использовать article.chapters[0], чтобы получить доступ к главе 1, и использовать article.chapters[0].subchapters[0], чтобы получить главу 1.1.

Чтобы достичь этого, итерация для организации данных будет:

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})
            }
        }
    };

Тот же принцип все еще применяется, если база данных более сложная, например, если каждый подглава содержит от нуля до нескольких вторичных подглав.

Теперь один объект article содержит всю информацию, которая нам может понадобитьсяотобразить статью в ее порядке.Простой запуск pug для отображения схемы будет выглядеть так:

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

Это может быть не совсем эффективно, но, по крайней мере, оно выполнит свою работу.Пожалуйста, скажите мне, если вы знаете лучшее решение.Удачного всем кодирования!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...