首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用值列表筛选多对多关系

使用值列表筛选多对多关系
EN

Stack Overflow用户
提问于 2021-07-21 13:33:35
回答 1查看 119关注 0票数 0

我在我的RESTful API中使用了objection.js和knex.js。

在我的数据库中,我有三个表:productscharacteristicsproduct_characteristics (具有额外列“value”的连接表)。

所以我要做的是获取所有具有相应特征值的产品。

在GET请求中,我接受一个characteristics查询参数并对其进行解析,以获得用于过滤产品的特征数组。

已解析的特征数组:

代码语言:javascript
复制
[{
   characteristicId: number,
   value: string
}, ...]

‘'products’表字段:

代码语言:javascript
复制
[id, title, price, discount]

‘特征表字段:

代码语言:javascript
复制
[id, name]

'product_characteristics‘连接表字段:

代码语言:javascript
复制
[productId, characteristicId, value]

目前,我使用objection的queryBuilderwithGraphFetch方法以及pagelimit方法获取所有产品:

代码语言:javascript
复制
const query: any = ProductModel.query()
  .page(page - 1, limit)
  .orderBy(sortBy, order)
  .withGraphFetched({
    category: true,
    images: true,
    characteristics: true,
  });

const result = await query;
return {
  products: result.results,
  total: result.total,
};

Objection.js提供了withGraphJoined方法,该方法允许访问queryBuilder中的相关实体,以便可以用于根据关系过滤parentModel,但它不支持pagelimit方法。

因此,一种可能的解决方案是使用knex.raw()方法执行原始SQL查询。但是我花了一天的时间尝试编写原始SQL查询来获取所有需要的数据。

理想的结果是一个经过特征过滤的产品数组,所有与产品相关的特征都作为JSON响应参数。

代码语言:javascript
复制
const products = [
  {
    id: 1,
    title: 'Pipe 1',
    price: 3000,
    discount: 500,
    characteristics: [
      {
        id: 1,
        name: 'diameter',
        value: '120 mm',
      },
      {
        id: 2,
        name: 'color',
        value: 'black',
      },
    ],
  },
  {
    id: 2,
    title: 'Pipe 2',
    price: 5000,
    discount: 0,
    characteristics: [
      {
        id: 1,
        name: 'diameter',
        value: '120 mm',
      },
      {
        id: 2,
        name: 'color',
        value: 'blue',
      },
    ],
  },
];
EN

Stack Overflow用户

回答已采纳

发布于 2021-07-21 19:51:05

我认为您尝试编写的SQL查询是

代码语言:javascript
复制
SELECT
  p.id,
  p.title,
  p.price,
  p.discount,
  c.name characteristicName,
  pc.value characteristicValue
FROM
  products p
  INNER JOIN product_characteristics pc ON pc.productId = p.id
  INNER JOIN characteristics c ON c.id = pc.characteristicId
WHERE
  (c.id = 1 AND pc.value = 'value1')
  OR (c.id = 2 AND pc.value = 'value2')
  OR (c.id = 3 AND pc.value = 'value3')

在knex中可以实现如下所示:

代码语言:javascript
复制
knex({p: 'products'})
  .join({pc: 'product_characteristics'}, 'pc.productId', '=', 'p.id')
  .join({c: 'characteristics'}, 'c.id', '=', 'pc.characteristicId')
  .where(builder =>
    characteristics.forEach(item =>
      builder.orWhere(builder =>
        builder
          .andWhere('c.id', '=', item.characteristicId)
          .andWhere('pc.value', '=', item.value)
      )
    )
  )
  .select('p.id', 'p.title', 'p.price' /* etc */)

您可以很容易地向其中添加.offset().limit(),以支持分页。它将转换为以下SQL:

代码语言:javascript
复制
select
  "p"."id",
  "p"."title",
  "p"."price"
from
  "products" as "p"
  inner join "product_characteristics" as "pc" on "pc"."productId" = "p"."id"
  inner join "characteristics" as "c" on "c"."id" = "pc"."characteristicId"
where
  (
    (
      "c"."id" = 1
      and "pc"."value" = 'value1'
    )
    or (
      "c"."id" = 2
      and "pc"."value" = 'value2'
    )
    or (
      "c"."id" = 3
      and "pc"."value" = 'value3'
    )
  )
票数 0
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68464438

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档