2
votes

I apologise for the lengthy post in advance!

I am trying to use sequelize in nodeJs to query a Wordpress mysql database with a required: true in a nested include.

However, the generated query includes a bad join (I'd expect the join to be nested like the nested where clause). I don't seem to be able to figure out if I've configured my schema incorrectly or whether I am just doing something else silly.

Any help would be greatly appreciated!

In essence, my schema is:

const Post = sequelize.define('wp_posts', {
  ID: {
    type: DataType.BIGINT,
    primaryKey: true
  }
});

const TermRelationship = sequelize.define('wp_term_relationships', {
  object_id: {
    type: DataType.BIGINT,
    primaryKey: true,
    allowNull: false
  },
  term_taxonomy_id: {
    type: DataType.BIGINT,
    primaryKey: true,
    allowNull: false
  }
});

const TermTaxonomy = sequelize.define('wp_term_taxonomy', {
  term_taxonomy_id: {
    type: DataType.BIGINT,
    primaryKey: true
  }
});

const Term = sequelize.define('wp_terms', {
  term_id: {
    type: DataType.BIGINT,
    primaryKey: true
  }
});

The relationships I have defined are:

Post.belongsToMany(TermTaxonomy, {
  through: TermRelationship,
  otherKey: 'term_taxonomy_id',
  foreignKey: 'object_id',
  as: 'termTaxonomies'
});

TermTaxonomy.belongsTo(Term, {
  foreignKey: 'term_id',
  as: 'term'
});

The query I am executing is

const query = {
  limit: 1,
  include: [
    {
      model: TermTaxonomy,
      required: true,
      as: 'termTaxonomies',
      include: [
        {
          model: Term,
          as: 'term',
          required: true,
        }
      ]
    }
  ]
};

However, the generated query includes a bad join. Here is the generated query. I have included comments where I see the errors:

SELECT
    `wp_posts`.*,
    `termTaxonomies`.`term_taxonomy_id` AS `termTaxonomies.term_taxonomy_id`,
    `termTaxonomies`.`term_id` AS `termTaxonomies.term_id`,
    `termTaxonomies`.`taxonomy` AS `termTaxonomies.taxonomy`,
    `termTaxonomies`.`description` AS `termTaxonomies.description`,
    `termTaxonomies`.`parent` AS `termTaxonomies.parent`,
    `termTaxonomies`.`count` AS `termTaxonomies.count`,
    `termTaxonomies->wp_term_relationships`.`object_id` AS `termTaxonomies.wp_term_relationships.object_id`,
    `termTaxonomies->wp_term_relationships`.`term_taxonomy_id` AS `termTaxonomies.wp_term_relationships.term_taxonomy_id`,
    `termTaxonomies->wp_term_relationships`.`term_order` AS `termTaxonomies.wp_term_relationships.term_order`
FROM
    (
        SELECT
            `wp_posts`.`ID`,
            `wp_posts`.`post_author`,
            `wp_posts`.`post_date_gmt`,
            `wp_posts`.`post_content`,
            `wp_posts`.`post_title`,
            `wp_posts`.`post_excerpt`,
            `wp_posts`.`post_status`,
            `wp_posts`.`comment_status`,
            `wp_posts`.`ping_status`,
            `wp_posts`.`post_password`,
            `wp_posts`.`post_name`,
            `wp_posts`.`to_ping`,
            `wp_posts`.`pinged`,
            `wp_posts`.`post_modified_gmt`,
            `wp_posts`.`post_content_filtered`,
            `wp_posts`.`post_parent`,
            `wp_posts`.`guid`,
            `wp_posts`.`menu_order`,
            `wp_posts`.`post_type`,
            `wp_posts`.`post_mime_type`,
            `wp_posts`.`comment_count`,
            -- ERROR
            -- wp_terms cannot be joined to wp_posts
            `termTaxonomies->term`.`term_id` AS `termTaxonomies.term.term_id`,
            `termTaxonomies->term`.`name` AS `termTaxonomies.term.name`,
            `termTaxonomies->term`.`slug` AS `termTaxonomies.term.slug`,
            `termTaxonomies->term`.`term_group` AS `termTaxonomies.term.term_group`
        FROM
            `wp_posts` AS `wp_posts`
            -- ERROR: bad join!
            -- wp_terms cannot be joined to wp_posts
            INNER JOIN `wp_terms` AS `termTaxonomies->term` ON `termTaxonomies`.`term_id` = `termTaxonomies->term`.`term_id`
        WHERE
            (
                SELECT
                    `wp_term_relationships`.`object_id`
                FROM
                    `wp_term_relationships` AS `wp_term_relationships`
                    INNER JOIN `wp_term_taxonomy` AS `wp_term_taxonomy` ON `wp_term_relationships`.`term_taxonomy_id` = `wp_term_taxonomy`.`term_taxonomy_id`
                    INNER JOIN `wp_terms` AS `wp_term_taxonomy->term` ON `wp_term_taxonomy`.`term_id` = `wp_term_taxonomy->term`.`term_id`
                WHERE
                    (
                        `wp_posts`.`ID` = `wp_term_relationships`.`object_id`
                    )
                LIMIT
                    1
            ) IS NOT NULL
        LIMIT
            1
    ) AS `wp_posts`
    INNER JOIN (
        `wp_term_relationships` AS `termTaxonomies->wp_term_relationships`
        INNER JOIN `wp_term_taxonomy` AS `termTaxonomies` ON `termTaxonomies`.`term_taxonomy_id` = `termTaxonomies->wp_term_relationships`.`term_taxonomy_id`
    ) ON `wp_posts`.`ID` = `termTaxonomies->wp_term_relationships`.`object_id`;

The error I get is 'Unknown column 'termTaxonomies.term_id' in 'on clause' due to the incorrect join.

The generated query is valid if I either remove required: true or the limit option since it no longer does the strange inner join. However, I just can't seem to get this to work with a required nested include.

FYI: I am using sequelize 4.37.10 with 1.5.3 mysql2 1.5.3.

Thank you very much!

1

1 Answers

-1
votes

When eager loading, we can force the query to return only those records which have an associated model, effectively converting the query from the default OUTER JOIN to an INNER JOIN. Just remove required:true it will work fine generally this happens when we eager load, probably in your case we are eagerloading.

I hope you find this explanation beneficial.