Strapi 按多对多关系过滤

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

我在strapi的postgresql中有两个表:商品和标签

Goods:
id | title
---------
1 | some name
2 | some name 2
3 | some name 4
…………………

Labels
id | title
------------
1 | some label 1
2 | some label 2
3 | some label n
………………………

它们通过附加表彼此多对多连接

goods_labels__labels_goods
id | good_id      | label_id
----------------------------
1  |  1           | 1
2  |  1           | 2
2  |  2           | 1

我需要选择与 label.id = 1 和 label.id = 2 都有关系的商品,这只是第一个 id = 1 的商品。有什么方法可以使用带有 graphql 或 bookshelf 的标准 Strapi 工具来实现它,或者作为最后的手段通过原始查询? 我还需要对这个请求进行排序和限制

node.js postgresql strapi bookshelf.js
2个回答
1
投票

好的。内容就在这里

我在 Strapi 中有两种内容类型,例如标签和文章。并且想要过滤具有多个标签(例如1、2、4)的文章。在标准的 Strapi 中,你不能这样做。所以我必须更改 Strapi 文章 api 的默认行为。您可以在这里

找到该文档

首先

我们需要定义特殊参数来实现我们的目标。事实上我在查询参数中选择了 multiTag

query{
    multiTag: [1,2,3]   
}

第二

在您的项目中打开文件

/src/api/article/controllers/article.js

!注意:路径会随着您的内容类型名称而变化。

你应该得到这个

const { createCoreController } = require('@strapi/strapi').factories;

module.exports = createCoreController('api::article.article');

然后添加一些代码

async function getMultiTag(conn, multiTag){
    // the sql should like this 
    const sql = `
        select 
            t.id 
        from 
            article t 
        inner join (
            select article_id from article_link_tag 
            where tag_id in (${string(multiTag})
            group by article_id having count(*) = ${multiTag.length}
        )t2 on t.id = t2.article_id
    `
    const result = await conn.raw(sql)
    // result should like this 

[
    // actual data
    [
        {"id" : 1}  
    ],
  // meta info
    [
    {
        "db" : 1
    }
    ]
]

    return result[0]
}

module.exports = createCoreController('api::pet-article.pet-article', ({ strapi }) => ({
   async find(ctx) {
    ctx.query = { ...ctx.query, local: 'en' }
        // get the param
    const multiTag = ctx.query?.multiTag
    if (multiTag && typeof multiTag == 'object' && multiTag.length > 0) {
            // get the database connection
      const conn = strapi.db.connection
      const articles = await getMultiTag(conn, multiTag)
            // when you have got the ids of article 
            // you can do many things
            // like this 
            ctx.query.filter = {
                ...(ctx.query.filter || {}),
                id: {
                    $in: articles.map(val => val.id)
                }
            }
            // or just return the ids
            // return { data: articles }
    }
    const { data, meta } = await super.find(ctx);
    meta.date = Date.now()
    return { data, meta };
  },
}));

0
投票

我还没有测试过它,但根据文档,尝试这个:

const hasAnyLabel = {
  labels: {
    id: {
      $in: [1,2]
    }
  }
};

const hasAllLabels = {
  labels: {
    $and: [
      {id: 1},
      {id: 2},
    ]
  }
};

const goods = await strapi.db.query('api::goods.goods').findMany({
  where: hasAllLabels,
  populate: ['labels']
});
© www.soinside.com 2019 - 2024. All rights reserved.