Django联系人重复检测异常:重复项计数始终为1的问题排查
联系人重复项排查与修复
问题描述
我有一个大型联系人数据库,每个联系人归属特定用户,需要移除各用户联系人列表内的重复项。最初采用拼接user_id||name||address||zipcode等字段生成dupe_id,再通过annotate统计计数并筛选count>1的方式,多数情况有效,但部分明确的重复项计数始终为1。
测试代码
neighbors = neighbors.filter(name__icontains='JOHN WILLIAMS') keyed_neighbors = neighbors.values('user_id', 'name', 'address', 'zipcode', 'pk' ).annotate(dupe_id=Concat( Cast('user_id', CharField(max_length=25)), Value('||'), Upper('name'), Value('||'), Upper('address'), Value('||'), Substr('zipcode', 1, 5), Value('||'), Upper('address_line_two'), output_field=CharField())) dupes = keyed_neighbors.annotate(dupe_id_count=Count('dupe_id'))
返回结果子集
{'dupe_id': u'174563||JOHN WILLIAMS||222 WEDGEFIELD DR||28376||', 'dupe_id_count': 1} {'dupe_id': u'175875||JOHN WILLIAMS||4 TALLIN CT||29607||', 'dupe_id_count': 1} {'dupe_id': u'175875||JOHN WILLIAMS||4 TALLIN CT||29607||', 'dupe_id_count': 1} {'dupe_id': u'177178||JOHN WILLIAMS||5106 PAUL PEEL PL||28348||', 'dupe_id_count': 1} {'dupe_id': u'51||JOHN WILLIAMS||2410 COLGATE DR||28304||', 'dupe_id_count': 1} {'dupe_id': u'51||JOHN WILLIAMS||2410 COLGATE DR||28304||', 'dupe_id_count': 1} {'dupe_id': u'51||JOHN WILLIAMS||4 TALLIN CT||29607||', 'dupe_id_count': 1}
问题原因
问题出在values()方法里包含了pk字段。Django中,values()指定的字段会作为GROUP BY的分组依据,而pk是每个联系人的唯一标识,即使其他字段完全相同,只要pk不同,就会被分成不同的组,导致每个组的dupe_id_count始终为1。
修复方案
把pk从values()的参数列表中移除,这样分组就会基于user_id、name、address、zipcode这些用来生成dupe_id的字段,相同dupe_id的记录会被分到同一组,计数就能正确统计:
neighbors = neighbors.filter(name__icontains='JOHN WILLIAMS') keyed_neighbors = neighbors.values('user_id', 'name', 'address', 'zipcode' ).annotate(dupe_id=Concat( Cast('user_id', CharField(max_length=25)), Value('||'), Upper('name'), Value('||'), Upper('address'), Value('||'), Substr('zipcode', 1, 5), Value('||'), Upper('address_line_two'), output_field=CharField())) dupes = keyed_neighbors.annotate(dupe_id_count=Count('dupe_id')).filter(dupe_id_count__gt=1)
如果需要保留每个重复组的pk信息,可以在统计出重复的dupe_id后,再关联查询对应的记录。
内容的提问来源于stack exchange,提问作者Psyferre
相关产品推荐
相关产品推荐

