【问题标题】:How to have multiple words contained in a search如何在搜索中包含多个单词
【发布时间】:2018-09-29 18:36:20
【问题描述】:

我正在尝试创建一个搜索栏,根据使用的字符串不断缩小数据库中的行。我希望能够让我的搜索包含多个单词,并让每个单词搜索不同的列。

example.db

Make      Model      Year
------    ------     ------
Toyota    Corolla    2000
Toyota    Corolla    2002
Toyota    Camry      2000
Toyota    Camry      2002
Honda     Civic      2002

这就是我目前所拥有的......

@app.route("/search")
def search():
    q = request.args.get("q") #q is a string containing make, model, and/or year 

    car = db.execute("SELECT * FROM places WHERE Make LIKE :q\
                                              OR Model LIKE :q\
                                              OR Year LIKE :q, q=q+"%")

现在,如果我只搜索一列,这将有效。如果我有 /search?q=corolla,它将选择带有模型 corolla 的两行。如果我有 /search?q=toyota+corolla,它将不选择任何行,因为没有单列有 toyota corolla。

我想让我在 q 中输入的信息越多,我的搜索结果就会越窄
即。

  1. /search?q=toyota 返回 4 行
  2. /search?q=toyota+corolla 返回 2 行
  3. /search?q=toyota+corolla+2000 返回 1 行

我已经在谷歌上搜索了一段时间,但我似乎无法正确表达我的问题。到目前为止,我已经尝试用空格分割字符串并查询每个单词,但这与单独搜索它们是一样的。我还尝试在 q 前面添加一个通配符,但这根本没有解决搜索中有多个单词的问题。我完全被什么感觉是简单的东西难住了。如果重要的话,输入将始终按品牌、型号、年份的顺序排列。任何帮助表示赞赏。

【问题讨论】:

  • q= '2; drop table places; --'protecting-against-sql-injection-in-python
  • 您将需要不同的语句 - 拆分 q 并且如果 2 个项目执行 'WHERE make = :q AND model = :q' .. 不确定 :q 您的语法对我来说看起来很奇怪。 - execute(statement using placeholders, (tuple of parameters to fill placeholders)) 是我在 python 中看到 sql 语句的正常方式
  • 从作曲的角度来看,拆分路线可能会更好:/search?make=toyota&model=corolla&year=2000 匹配所有 3
  • 我相信它已经清理了字符串,但忽略它。

标签: python sql python-3.x algorithm sqlite


【解决方案1】:

您试图以错误的方式解决全文搜索问题。我强烈建议您使用数据库提供的全文搜索功能,而不是与列进行比较。请参阅 sqlite3 here 中 FTS 的实现。

【讨论】:

  • 使用 FTS 后问题变得微不足道。这正是我正在寻找的行为。
【解决方案2】:

我建议您使用全文搜索——假设您正在寻找完整的单词。但是您可以使用like 来完成这项工作。换一种方式进行比较:

WHERE :q LIKE '%' || Make || '%' OR
      :q LIKE '%' || Model || '%' OR
      :q LIKE '%' || Year || '%' 

如果您需要所有单词都匹配,那么您可以接近:

WHERE ( (CASE WHEN :q LIKE '%' || Make || '%' THEN 1 ELSE 0 END) +
        (CASE WHEN :q LIKE '%' || Model || '%' THEN 1 ELSE 0 END) +
        (CASE WHEN :q LIKE '%' || Year || '%'  THEN 1 ELSE 0 END)
      ) = <# of words in :q>

这并不准确,但可能足以满足您的目的。

【讨论】:

    【解决方案3】:

    如果给定的参数为空,我相信这种情况应该返回基本上忽略过滤器......

    WHERE 
    (Make = @Make OR CASE WHEN @Make IS NULL THEN 1 ELSE 0 END = 1)
    AND
    (Model = @Model OR CASE WHEN @Model IS NULL THEN 1 ELSE 0 END = 1)
    AND
    (Year = @Year OR CASE WHEN @Year IS NULL THEN 1 ELSE 0 END = 1)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-11
      • 2013-05-18
      • 2020-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多