包含对象,部分匹配的对象的Python搜索列表

时间:2011-01-28 14:22:49

标签: python search full-text-search pymssql

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

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

预期功能:根据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语句可能会导致将重复的产品添加到结果中。

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

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

编辑: 我有一个包含产品列表的Category对象的原因是我想显示按类别组织的产品的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

2 个答案:

答案 0 :(得分:0)

如果您不需要子字符串的位置,请准备循环外的所有变量并使用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

答案 1 :(得分:0)

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

由于产品数量较少,我建议您构建一个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)