【问题标题】:Python search list of objects that contain objects, partial matchesPython搜索包含对象的对象列表,部分匹配
【发布时间】:2011-01-28 14:22:49
【问题描述】:

我正在尝试为一个小型网站构建一个简单的搜索引擎。我最初的想法是避免使用较大的软件包,例如 Solr、Haystack 等,因为我的搜索需求过于简单。

我希望通过一些指导,我可以使我的代码更加 Python 化、高效,最重要的是能够正常运行。

预期功能:根据 item_number、产品名称或类别名称的全部或部分匹配返回产品结果(目前没有实现类别匹配)

一些代码:

import pymssql import utils #My utilities class Product(object): def __init__(self, item_number, name, description, category, msds): self.item_number = str(item_number).strip() self.name = name self.description = description self.category = category self.msds = str(msds).strip() class Category(object): def __init__(self, name, categories): self.name = name self.categories = categories self.slug = utils.slugify(name) self.products = [] categories = ( Category('Food', ('123', '12A')), Category('Tables', ('354', '35A', '310', '31G')), Category('Chemicals', ('845', '85A', '404', '325')) ) products = [] conn = pymssql.connect(...) curr = conn.cursor() for Category in categories: for c in Category.categories: curr.execute('SELECT item_number, name, CAST(description as text), category, msds from tblProducts WHERE category=%s', c) for row in curr: product = Product(row[0], row[1], row[2], row[3], row[4]) products.append(product) Category.products.append(product) conn.close() def product_search(*params): results = [] for product in products: for param in params: name = str(product.name) if (name.find(param.capitalize())) != -1: results.append(product) item_number = str(product.item_number) if (item.number.find(param.upper())) != -1: results.append(product) print results product_search('something')

带有我无法更改的表和字段的 MS SQL 数据库。
最多拉200个左右的产品。

有些事情让我大吃一惊。嵌套 for 循环。产品搜索中有两个不同的 if 语句,这可能会导致将重复的产品添加到结果中。

我的想法是,如果我将产品放在内存中(产品很少会改变),我可以缓存它们,从而减少对数据库的依赖并可能提供有效的搜索。

...暂时发布...将回来并添加更多想法

编辑: 我有一个包含产品列表的类别对象的原因是我想显示按类别组织的产品的 html 页面。此外,实际的类别编号将来可能会发生变化,并且持有一个元组似乎是简单的无痛解决方案。那和我对数据库的只读访问权限。

单独列出产品列表的原因有点作弊。我有一个页面显示所有能够查看 MSDS(安全表)的产品。它还提供了一个在搜索时遍历的更少的级别。

编辑 2:

def product_search(*params): results = [] lowerParams = [ param.lower() for param in params ] for product in products: item_number = (str(product.item_number)).lower() name = (str(product.name)).lower() for param in lowerParams: if param in item_number or param in name: results.append(product) print results

【问题讨论】:

    标签: python search full-text-search pymssql


    【解决方案1】:

    准备循环外的所有变量,如果不需要子字符串的位置,请使用in 而不是.find

    def product_search(*params):
        results = []
        upperParams = [ param.upper() for param in params ]
    
        for product in products:
            name = str(product.name).upper()
            item_number = str(product.item_number).upper()
            for upperParam in upperParams:
                if upperParam in name or upperParam in item_number:
                    results.append(product)
        print results
    

    【讨论】:

    • 产品名称大写,但 item_number 始终全部大写,并且可能包含数字。例如 item_number = 147DECAF。所以我认为我需要区分name和item_number。
    • 你不必str() "147DECAF" - 它看起来已经像一个字符串了。
    • 如果有人搜索147,那不是整数吗?可能有多个 item_numbers 包含 147. 147DECAF、147CAF、147BLAH 等。
    • 没有。所有用户输入都被视为字符串,不会自动转换。除非必要,否则进行类型检查/转换也是非常不寻常的。
    • 好的,谢谢。我不知道。将输入与 item_numbers 匹配的问题如何?例如: 'Decaf' 需要匹配 '147DECAF' 我可以进行不区分大小写的比较吗?不区分大小写的搜索将解决产品名称和产品 item_number 的情况。
    【解决方案2】:

    如果名称和编号都与搜索参数匹配,则该产品将在结果列表中出现两次。

    由于产品数量很少,我建议构造一个SELECT 查询,如:

    def search(*args):
        import operator
        cats = reduce(operator.add, [list(c.categories) for c in categories], [])
    
        query = "SELECT * FROM tblProducts WHERE category IN (" + ','.join('?' * len(cats)) + ") name LIKE '%?%' or CAST(item_number AS TEXT) LIKE '%?%' ..."
        curr.execute(query, cats + list(args)) # Not actual code
        return list(curr)
    

    【讨论】:

    • 嗯,实际的表 (tblProducts) 包含数千条记录。这就是为什么我尝试查询现有对象而不是执行非常耗时的查询的原因。
    • 那么您的products 列表也将包含内存中的数千条记录。您可以做的最好的事情是实际测量这样的查询需要多少时间。
    • 为什么会包含数千条记录?在我的 SQL 查询中,我只从表中提取与我定义的类别匹配的产品。
    • 我会试试这个,但我有点迷失了我需要填写的内容......和#Not实际代码。这可能需要我一分钟。
    • 我无法控制数据库的索引。根据特定类别从数千个表中查找约 200 种产品的第一个查询相当耗时。我希望避免查询两次。
    猜你喜欢
    • 1970-01-01
    • 2014-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-10
    • 2019-10-22
    • 2014-07-11
    • 1970-01-01
    相关资源
    最近更新 更多