如何使用子表中的数据在Sequelize中查找数据

时间:2018-07-01 12:45:04

标签: node.js sequelize.js

因此,我使用Sequelize创建了此查询以在数据库中查找配置文件,但我希望能够使用存储在不同(子)表/模型中的条件(不仅在主表中)查找结果。

这是我的代码的功能摘要:

同步模型设置:

const Profile = sequelize.define('profiles',
    { // Database columns:
        profile_id: {
            type: Sequelize.STRING,
            primaryKey: true
        },
        user_name: {
            type: Sequelize.STRING,
            unique: true
        }
    });

const Email = sequelize.define('profiles_emails',
    { // Database columns:
        entry_id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        owner_id: {
            type: Sequelize.STRING,
        },
        email_address: {
            type: Sequelize.STRING,
        }
    });

const Phone = sequelize.define('profiles_phones',
    { // Database columns:
        entry_id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        owner_id: {
            type: Sequelize.STRING,
        },
        phone_number: {
            type: Sequelize.STRING,
        }
    });

设置关联:

Profile.hasMany(Email,
    { // Options:
        foreignKey: 'owner_id'
    });

Profile.hasMany(Phone,
    { // Options:
        foreignKey: 'owner_id'
    });

Profile.hasOne(Password,
    { // Options:
        foreignKey: 'owner_id'
    });

执行:

// TODO: Finding by email and phone does not work because finding in other tables than the parent table is not programed.
Profile
    .findAll({
       where: {
           [Op.or]: [
               { profile_id: '665C70C2A9F9' },
               { user_name: 'user1' },
               { email_address: 'user1@mail.com' }, 
               { phone_number: '554111222' }]
        },
        include: [Phone, Email], // Tables that I want to fetch data from.
    })
    .then(function(data) {
        if (data) { console.log('Number of rows found: ' + data.length, JSON.stringify(data)) }
        else { console.log('No entries found.') }
    })
    .catch(function(data) { console.error('An error occurred while making the query:\n' + data) });

“电子邮件地址”和“电话号码”列存储在不同的子表中,并且Sequelize关联已成功建立。

从实际角度进行解释:即使这些标准位于不同的关联模块中,我也希望能够通过电话和电子邮件获取用户。

关于如何执行此操作的任何想法?我已经尝试过了,但没有成功:http://docs.sequelizejs.com/manual/tutorial/models-usage.html#top-level-where-with-eagerly-loaded-models

根据Vivek Doshi的建议进行更新:

因此,这是第一个建议

Profile
    .findAll({
        where: {
            [Op.or]: [
                { profile_id: '665C70C2A9F9' },
                { user_name: 'user1' },
                { '$profiles_emails.email_address$': 'user1@mail.com' },
                { '$profiles_phones.phone_number$': '554111222' }
            ],
        },
        include: [Phone, Email], // Tables that I want to fetch data from.
        limit: 5 // Limit of profiles to look for.
    })
    .then(function(data) {
        if (data) { console.log('Number of rows found: ' + data.length, JSON.stringify(data)) }
        else { console.log('No entries found.') }
    })
    .catch(function(data) { console.error('An error occurred while making the query:\n' + data) });

这会导致错误:

Executing (default): SELECT `profiles`.*, `profiles_phones`.`entry_id` AS `profiles_phones.entry_id`, `profiles_phones`.`owner_id` AS `profiles_phones.owner_id`, `profiles_phones`.`phone_number` AS `profiles_phones.phone_number`, `profiles_phones`.`verified` AS `profiles_phones.verified`, `profiles_phones`.`modified_time` AS `profiles_phones.modified_time`, `profiles_phones`.`modified_by` AS `profiles_phones.modified_by`, `profiles_emails`.`entry_id` AS `profiles_emails.entry_id`, `profiles_emails`.`owner_id` AS `profiles_emails.owner_id`, `profiles_emails`.`email_address` AS `profiles_emails.email_address`, `profiles_emails`.`verified` AS `profiles_emails.verified`, `profiles_emails`.`modified_time` AS `profiles_emails.modified_time`, `profiles_emails`.`modified_by` AS `profiles_emails.modified_by` FROM (SELECT `profiles`.`profile_id`, `profiles`.`user_name`, `profiles`.`modified_time`, `profiles`.`modified_by` FROM `profiles` AS `profiles` WHERE (`profiles`.`profile_id` = '665C70C2A9F9' OR `profiles`.`user_name` = 'user1' OR `profiles_emails`.`email_address` = 'user1@mail.com' OR `profiles_phones`.`phone_number` = '554111222') LIMIT 5) AS `profiles` LEFT OUTER JOIN `profiles_phones` AS `profiles_phones` ON `profiles`.`profile_id` = `profiles_phones`.`owner_id` LEFT OUTER JOIN `profiles_emails` AS `profiles_emails` ON `profiles`.`profile_id` = `profiles_emails`.`owner_id`;

An error occurred while making the query:
SequelizeDatabaseError: Unknown column 'profiles_emails.email_address' in 'where clause'

这是第二条建议

Profile
    .findAll({
        where: {
            [Op.or]: [
                { profile_id: '665C70C2A9F9' },
                { user_name: 'user1' },
            ],
        },
        include: [{
            model : Phone,
            where : { phone_number: '554111222' } ,
            required : false
        }, {
            model : Email,
            where : { email_address: 'user1@mail.com' } ,
            required : false
        }],
        limit: 5 // Limit of profiles to look for.
    })
    .then(function(data) {
        if (data) { console.log('Number of rows found: ' + data.length, JSON.stringify(data)) }
        else { console.log('No entries found.') }
    })
    .catch(function(data) { console.error('An error occurred while making the query:\n' + data) });

这将导致:

Executing (default): SELECT `profiles`.*, `profiles_phones`.`entry_id` AS `profiles_phones.entry_id`, `profiles_phones`.`owner_id` AS `profiles_phones.owner_id`, `profiles_phones`.`phone_number` AS `profiles_phones.phone_number`, `profiles_phones`.`verified` AS `profiles_phones.verified`, `profiles_phones`.`modified_time` AS `profiles_phones.modified_time`, `profiles_phones`.`modified_by` AS `profiles_phones.modified_by`, `profiles_emails`.`entry_id` AS `profiles_emails.entry_id`, `profiles_emails`.`owner_id` AS `profiles_emails.owner_id`, `profiles_emails`.`email_address` AS `profiles_emails.email_address`, `profiles_emails`.`verified` AS `profiles_emails.verified`, `profiles_emails`.`modified_time` AS `profiles_emails.modified_time`, `profiles_emails`.`modified_by` AS `profiles_emails.modified_by` FROM (SELECT `profiles`.`profile_id`, `profiles`.`user_name`, `profiles`.`modified_time`, `profiles`.`modified_by` FROM `profiles` AS `profiles` WHERE (`profiles`.`profile_id` = 'user1' OR `profiles`.`user_name` = 'jorge') AND ( SELECT `owner_id` FROM `profiles_phones` AS `profiles_phones` WHERE (`profiles_phones`.`phone_number` = '9' AND `profiles_phones`.`owner_id` = `profiles`.`profile_id`) LIMIT 1 ) IS NOT NULL LIMIT 5) AS `profiles` INNER JOIN `profiles_phones` AS `profiles_phones` ON `profiles`.`profile_id` = `profiles_phones`.`owner_id` AND `profiles_phones`.`phone_number` = '9' LEFT OUTER JOIN `profiles_emails` AS `profiles_emails` ON `profiles`.`profile_id` = `profiles_emails`.`owner_id` AND `profiles_emails`.`email_address` = 'user1@mail.com';

这一行工作并找到行。但是,它获取与“主要”模型的结果相关的结果(即,通过userid / user_name查找数据,然后根据是否匹配其他数据(电子邮件和电话)来查找或不包含这些结果)。这不是我现在想要的,我希望能够使用其他表中的条件/列查找具有所有数据和相同结构的完整配置文件。

1 个答案:

答案 0 :(得分:0)

在这里,这是通过Sequelize获得预期结果的方法

Profile
    .findAll({
       where: {
           [Op.or]: [
               { profile_id: '665C70C2A9F9' },
               { user_name: 'user1' }
           ]
        },
        include: [ { 
                model : Phone ,
                where : { phone_number: '554111222' } ,
                required : false // as you want it in OR relation relation
            }, { 
                model : Email
                where : { email_address: 'user1@mail.com' } ,
                required : false // as you want it in OR relation relation
            }]
    })

OR

Profile
    .findAll({
       where: {
           [Op.or]: [
               { profile_id: '665C70C2A9F9' },
               { user_name: 'user1' },
               { '$profiles_emails.email_address$': 'user1@mail.com' }, 
               { '$profiles_phones.phone_number$': '554111222' }]
        },
        include: [Phone, Email], // Tables that I want to fetch data from.
    })