Django:使用自定义搜索算法查询数据库

时间:2018-01-17 18:33:04

标签: python django

上下文:我有一个房屋数据库,用户可以按位置名称​​查询(例如,纽约,纽约和第一街100号,旧金山')。除了每个对象的列表之外,我还使用Google Maps API在每个查询结果的地图上检索精确定位点。 我分别使用Django和Postgres作为我的框架和数据库。

问题:我想知道如何按位置过滤House个对象,但并非所有位置查询都包含相同的信息(即某些可能有自己的号码) ,有些可能有城市或州,有些可能没有)。

如下面的代码所示,每个House对象都通过OneToOneField链接到包含必要字段的Location对象。

每个Location对象由多个字段组成,而查询将是一个字符串,可能与单个字段不匹配,因为您在Django' s { {1}}方法。诸如' 100 1st Street,San Francisco' 之类的查询与任何单个filter()字段都不匹配,因为此查询由多个字段组成。我如何编写一种排序算法来查找与所描述的匹配给定查询的任何对象?

代码

models.py:

Location

views.py:

class House(models.Model):
    ...
    mapped_location = models.OneToOneField(Location, related_name='location_house')
    ...

class Location(models.Model):
    ...
    name = models.CharField(...)
    street_name = models.CharField(...)
    city = models.CharField(...)

如果我需要发布更多代码,请告诉我,谢谢!

3 个答案:

答案 0 :(得分:2)

第一步是标记搜索词,然后您可以根据各个部分构建查询。 标记化可能相当复杂,因此为了获得最佳结果,您可能希望从现有的库开始,例如https://github.com/datamade/usaddress。谷歌搜索其他选项的“python地址标记化”。

接下来,您可以使用Q objects

在查询中使用这些部分
from django.db.models import Q

House.objects.filter(
    Q(mapped_location__name="100") | 
    Q(mapped_location__street_name="1st Street") | 
    Q(mapped_location__city="San Francisco")
)

(但将上面的字符串常量替换为tokenizer的结果)

答案 1 :(得分:1)

您通过请求GET以逗号分隔的字段传递查询字符串,并分别检查模型字段中的每个字段,您的show_results将如下:

from django.db.models import Q

def show_results(request):
    q = request.GET.get('query')
    results = []
    for query in unquote(q).split(','):
        query = query.strip()
        results += list(House.objects.filter(Q(mapped_location__name=query) | Q(mapped_location__street_name=query) | Q(mapped_location__city=query)))
    context['results'] = results
    return render(request, 'results.html', context)

您可以使用变量results

获取结果

答案 2 :(得分:0)

如果您为用户提供免费,未经验证的自然语言输入机会,您需要查看一组不同的工具,即面向自然语言处理的工具。

第一步是令牌识别,解密输入字符串的哪些部分是街道号码,街道名称,城市,州等。这类似于词性分析,但语法不同。

如果要考虑拼写错误和不准确性,下一步是“模糊匹配”,也就是使用levenshtein编辑距离或ngram分析来找到每个标记类型的“规范”值中的“最佳”匹配。 / p>

从那里,你可以查询你的数据库。

重新关注实际问题,如何减轻未知的令牌组合,您可以选择通过某种界面或形式验证数据,或者采用上述的词性和nlp路径。< / p>