如何在sequelize中使用带有嵌套包含的全文搜索?

问题描述 投票:0回答:1

我正在使用 Sequelize 来处理 MariaDB 数据库,我需要对两列进行全文搜索:

order.comment
order.orderProducts.product.name

我已在

order.name
product.name
user.name
列上添加了 FULLTEXT 索引。

这是我的代码:

if (search) {
  where = Sequelize.literal(
    `MATCH(order.comment) AGAINST('*${search}*' IN BOOLEAN MODE) OR
    MATCH(orderProducts.product.name) AGAINST('*${search}*' IN BOOLEAN MODE) OR
    MATCH(user.name) AGAINST('*${search}*' IN BOOLEAN MODE)`,
  );
}

const orders = await this.orderModel.findAndCountAll({
  subQuery: false,
  limit,
  offset,
  distinct: true,
  order: [['id', 'DESC']],
  where,
  include: [
    {
      model: User,
    },
    {
      model: OrderProduct,
      include: [
        {
          model: Product,
        },
      ],
    },
  ],
});

当我搜索某些内容时,出现错误:

Unknown column 'orderProducts.product.name' in 'where clause'

没有

MATCH(orderProducts.product.name) AGAINST('*${search}*' IN BOOLEAN MODE)
一切正常。

我不明白为什么会发生这种情况以及如何解决它。我尝试了不同的选择,但没有成功。

我的模特:

@Table({
  tableName: 'orders',
  indexes: [{ type: 'FULLTEXT', fields: ['comment'] }],
})
export class Order extends Model<Order> {
  @Column({
    type: DataType.INTEGER,
    primaryKey: true,
    autoIncrement: true,
  })
  id: number;

  @Column({ type: DataType.TEXT, allowNull: false })
  comment: string;

  @HasMany(() => OrderProduct, { foreignKey: 'orderId' })
  orderProducts: OrderProduct[];
}
@Table({
  tableName: 'products',
  indexes: [{ type: 'FULLTEXT', fields: ['name'] }],
})
export class Product extends Model<Product> {
  @Column({
    type: DataType.INTEGER,
    primaryKey: true,
    autoIncrement: true,
  })
  id: number;

  @Column({ type: DataType.STRING, unique: true, allowNull: false })
  name: string;

  @HasMany(() => OrderProduct, { foreignKey: 'productId' })
  orderProducts: OrderProduct[];
}
@Table({ tableName: 'order_products' })
export class OrderProduct extends Model<OrderProduct> {
  @Column({
    type: DataType.INTEGER,
    primaryKey: true,
    autoIncrement: true,
  })
  id: number;

  @Column({ type: DataType.INTEGER, allowNull: false })
  price: number;

  @ForeignKey(() => Product)
  @Column({ type: DataType.INTEGER })
  productId: number;

  @ForeignKey(() => Order)
  @Column({ type: DataType.INTEGER })
  orderId: number;

  @BelongsTo(() => Product, { foreignKey: 'productId' })
  product: Product;

  @BelongsTo(() => Order, { foreignKey: 'orderId' })
  order: Order;
}

附注 我尝试过这些变化:

/* ----1---- */
if (search) {
  where = Sequelize.literal(
    `MATCH(product.name) AGAINST('*${search}*' IN BOOLEAN MODE)`,
  );
}
/* ----2---- */
if (search) {
  where = Sequelize.literal(
    `MATCH(Product.name) AGAINST('*${search}*' IN BOOLEAN MODE)`,
  );
}
/* ----3---- */
if (search) {
  where = Sequelize.literal(
    `MATCH(OrderProducts.Product.name) AGAINST('*${search}*' IN BOOLEAN MODE)`,
  );
}

错误是一样的。

SQL 查询出错:

sql: SELECT count(DISTINCT(`Order`.`id`)) AS `count` FROM `orders` AS `Order` LEFT OUTER JOIN `users` AS `user` ON `Order`.`userId` = `user`.`id` LEFT OUTER JOIN `order_products` AS `orderProducts` ON `Order`.`id` = `orderProducts`.`orderId` LEFT OUTER JOIN `products` AS `orderProducts->product` ON `orderProducts`.`productId` = `orderProducts->product`.`id`  WHERE MATCH(orderProducts.product.name) AGAINST('*hello*' IN BOOLEAN MODE); - parameters:[]
mariadb sequelize.js full-text-search
1个回答
0
投票

你可以看到Sequelize正在加入这样的产品:

LEFT OUTER JOIN `products` AS `orderProducts->product`

给它一个别名orderProducts->product,其中包含特殊字符,所以使用时需要用反引号括起来。所以你的文字 sql 应该使用列:

`orderProducts->product`.name

转义反引号以将其包含在模板文字中:

`MATCH(\`orderProducts->product\`.name) AGAINST('*${search}*' IN BOOLEAN MODE)`,
© www.soinside.com 2019 - 2024. All rights reserved.