【发布时间】:2015-08-19 21:48:47
【问题描述】:
我正在尝试创建一个从模型中查询多个属性的搜索功能。为了使事情变得更难,我希望能够在列表理解中使用多个术语来完成它,然后按更准确的结果进行排序。
例如,如果搜索项是 ['green', 'shoe'] 并且我有一个名为 'green shoe' 的对象,我希望它成为我结果中的第一项,然后是 'black shoe' 或 'green pants'。
这是我到目前为止从查询参数中提取搜索词然后运行 Q 查询的内容。
def get_queryset(self):
search_terms = self.request.GET.getlist('search', None)
terms = []
x = [terms.extend(term.lower().replace('/', '').split(" "))
for term in search_terms]
# x is useless, but it is just better to look at.
results = reduce(operator.or_,
(Item.objects.filter(Q(name__icontains=term) |
Q(description__icontains=term) |
Q(option__name__icontains=term))
for term in terms))
return results
这将返回无序的['black shoe', 'green pants', 'green shoe'],但它是所有匹配结果。
我意识到我可以让它不将搜索词分成多个词,只会得到一个结果,但我也不会得到其他类似的东西。
感谢观看
编辑 1
所以在第一个答案之后,我开始玩弄它。现在这产生了我想要的结果,但由于将查询集添加到列表中,我觉得这可能很糟糕。让我知道你的想法:
def get_queryset(self):
search_terms = self.request.GET.getlist('search', None)
if not search_terms or '' in search_terms or ' ' in search_terms:
return []
terms = [term.lower().replace('/', '').split(" ") for term in search_terms][0]
results = reduce(operator.or_,
(Item.objects.filter
(Q(name__icontains=term) | Q(description__icontains=term) | Q(option__name__icontains=term))
for term in terms))
# creating a list so I can index later
# Couldn't find an easy way to index on a generator/queryset
results = list(results)
# Using enumerate so I can get the index, storing index at end of list for future reference
# Concats the item name and the item description into one list, using that for the items weight in the result
results_split = [t.name.lower().split() + t.description.lower().split() + list((x,)) for x, t in enumerate(results)]
query_with_weights = [(x, len(search_terms[0].split()) - search_terms[0].split().index(x)) for x in terms]
get_weight = lambda x: ([weight for y, weight in query_with_weights if y==x] or [0])[0]
sorted_results = sorted([(l, sum([(get_weight(m)) for m in l])) for l in results_split], key=lambda lst: lst[1], reverse=True)
# Building the final list based off the sorted list and the index of the items.
final_sorted = [results[result[0][-1]] for result in sorted_results]
print results_split
print query_with_weights
print final_sorted
return final_sorted
[red, shoes, pants] 的查询将打印出以下内容:
# Combined name and description of each item
[[u'red', u'shoe', u'sweet', u'red', u'shoes', u'bro', 0], [u'blue', u'shoe', u'sweet', u'blue', u'shoes', u'bro', 1], [u'red', u'pants', u'sweet', u'red', u'pants', u'bro', 2], [u'blue', u'pants', u'sweet', u'blue', u'pants', u'bro', 3], [u'red', u'swim', u'trunks', u'sweet', u'red', u'trunks', u'bro', 4]]
# Weighted query
[(u'red', 3), (u'shoes', 2), (u'pants', 1)]
# Final list of sorted items from queryset
[<Item: Red Shoe>, <Item: Red Pants>, <Item: Red Swim Trunks>, <Item: Blue Shoe>, <Item: Blue Pants>]
【问题讨论】:
标签: python django python-2.7 django-queryset django-q