如何在SQLITE中进行多词部分搜索?

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

你好,我想在 SQLITE 中编写一个多词部分搜索:

  • 如果用户输入
    red
    ,我将给出名称、颜色或反应性中带有红色的所有抗体,并且
  • 如果用户输入
    red 20
    ,我想给出抗体名称或颜色或反应性中带有红色和20的交集。

我已经写了这个,但我认为 SQL 中应该有一些东西可以让它变得更容易。

    const searchMultiWord = (
      index: number,
      amount: number,
      information: string[],
      startDate: number,
      endDate: number,
    ) => {
      return new Promise<Antibodies[]>((resolve, reject) => {
        let antibodies: Antibodies[] = [];
        let totalCount: number;
        let defaultSql = `SELECT id, name as antibodyName 
                              FROM Antibodies 
                              WHERE id IN (
                                SELECT id FROM
                                (
                                  SELECT id FROM Antibodies WHERE name LIKE ?
                                  UNION all
                                  SELECT antiId FROM AssignedColors WHERE name LIKE ?
                                  UNION all
                                  SELECT antiId FROM AssignedReactivities WHERE name LIKE ?
                                )`;
        let defaultParams = [`${startDate}`, `${endDate}`, `${amount}`, `${index}`]
        for (let i = 0; i < information.length - 1; i++) {
          defaultSql += `INTERSECT
          SELECT id FROM
          (
            SELECT id FROM Antibodies WHERE name LIKE ?
            UNION all
            SELECT antiId FROM AssignedColors WHERE name LIKE ?
            UNION all
            SELECT antiId FROM AssignedReactivities WHERE name LIKE ?
          )`;
          defaultParams.unshift(`%${information[i]}%`, `%${information[i]}%`, `%${information[i]}%`);
        }
        defaultParams.unshift(`%${information[information.length - 1]}%`, `%${information[information.length - 1]}%`,
          `%${information[information.length - 1]}%`);
        defaultSql += `) AND dateOfCreation >= ? AND dateOfCreation <= ?
        ORDER BY dateOfCreation DESC LIMIT ? OFFSET?;`;
        db.serialize(() => {
          db.each(defaultSql,
            defaultParams
            , (err, antibody) => {
              if (err) {
                return err.message;
              } else {
                db.all('SELECT name, locations, colorId FROM AssignedColors WHERE antiId = ?', [antibody.id], (err, colors) => {
                  if (err) {
                    reject(err.message)
                  } else {
                    antibody.colors = colors;
                    antibodies.push(antibody);
                    if (totalCount === antibodies.length) {
                      resolve(antibodies);
                    }
                  }
                });
              }
            }, (err, count) => {
              if (err) {
                reject(err.message)
              } else {
                if (count === 0) {
                  resolve(antibodies);
                } else {
                  totalCount = count;
                }
              }
            });
        });
      });
    }
sql typescript sqlite node-sqlite3
1个回答
1
投票

为您要搜索的值创建一个

CTE
,例如
'red'
'20'
,以及另一个返回所有 3 个表的
CTE
id
列的
name

连接表
group by id
并在
HAVING
子句中设置条件:

WITH 
  search(val) AS (VALUES ('red'), ('20')), 
  cte AS (
    SELECT id, name FROM Antibodies
    UNION ALL
    SELECT antiId, name FROM AssignedColors
    UNION ALL
    SELECT antiId, name FROM AssignedReactivities
  )
SELECT c.id
FROM cte c INNER JOIN search s
ON c.name LIKE '%' || s.val || '%'  
GROUP BY c.id
HAVING COUNT(DISTINCT s.val) = (SELECT COUNT(*) FROM search)
© www.soinside.com 2019 - 2024. All rights reserved.