Python搜索包含对象的对象列表,部分匹配
我正在尝试为一个小网站建立一个简单的搜索引擎。最开始我想避免使用像Solr、Haystack这样的大型工具,因为我的搜索需求比较简单。
我希望在一些指导下,可以让我的代码更符合Python的风格,更高效,最重要的是能够正常工作。
我想要的功能是:根据商品编号、产品名称或类别名称的完全匹配或部分匹配返回产品结果(目前还没有实现类别匹配)。
以下是一些代码:
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
2 个回答
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)
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