对具有相同电话号码的文档进行分组

时间:2016-08-30 06:20:17

标签: python mongodb real-time aggregation-framework mongodb-aggregation

我的数据库包含一个大号的集合。酒店(约121,000)。

这就是我的收藏品的样子:

{
    "_id" : ObjectId("57bd5108f4733211b61217fa"),
    "autoid" : 1,
    "parentid" : "P01982.01982.110601173548.N2C5",
    "companyname" : "Sheldan Holiday Home",
    "latitude" : 34.169552,
    "longitude" : 77.579315,
    "state" : "JAMMU AND KASHMIR",
    "city" : "LEH Ladakh",
    "pincode" : 194101,
    "phone_search" : "9419179870|253013",
    "address" : "Sheldan Holiday Home|Changspa|Leh Ladakh-194101|LEH Ladakh|JAMMU AND KASHMIR",
    "email" : "",
    "website" : "",
    "national_catidlineage_search" : "/10255012/|/10255031/|/10255037/|/10238369/|/10238380/|/10238373/",
    "area" : "Leh Ladakh",
    "data_city" : "Leh Ladakh"
}

每个文档可以有一个或多个电话号码,用" |"分隔符。

我必须将具有相同电话号码的文件组合在一起。

实时,我的意思是当用户打开一个特定的酒店在网络界面上查看其详细信息时,我应该能够显示所有链接到它的酒店按照普通电话号码分组。

在分组时,如果一家酒店链接到另一家酒店并且酒店链接到另一家酒店,则所有3家酒店应归为一类。

  

示例:酒店A的电话号码为1 | 2,B的电话号码为3 | 4和C.   有电话号码2 | 3,那么A,B和C应该组合在一起。

from pymongo import MongoClient
from pprint import pprint #Pretty print 
import re #for regex
#import unicodedata

client = MongoClient()

cLen = 0
cLenAll = 0
flag = 0
countA = 0
countB = 0
list = []
allHotels = []
conContact = []
conId = []
hotelTotal = []
splitListAll = []
contactChk = []

#We'll be passing the value later as parameter via a function call 
#hId = 37443; 

regx = re.compile("^Vivanta", re.IGNORECASE)

#Connection
db = client.hotel
collection = db.hotelData

#Finding hotels wrt search input
for post in collection.find({"companyname":regx}):
    list.append(post)

#Copying all hotels in a list
for post1 in collection.find():
    allHotels.append(post1)

hotelIndex = 11 #Index of hotel selected from search result
conIndex = hotelIndex
x = list[hotelIndex]["companyname"] #Name of selected hotel
y = list[hotelIndex]["phone_search"] #Phone numbers of selected hotel

try:
    splitList = y.split("|") #Splitting of phone numbers and storing in a list 'splitList'
except:
    splitList = y


print "Contact details of",x,":"

#Printing all contacts...
for contact in splitList:   
    print contact 
    conContact.extend(contact)
    cLen = cLen+1

print "No. of contacts in",x,"=",cLen


for i in allHotels:
    yAll = allHotels[countA]["phone_search"]
    try:
        splitListAll.append(yAll.split("|"))
        countA = countA+1
    except:
        splitListAll.append(yAll)
        countA = countA + 1
#   print splitListAll

#count = 0 

#This block has errors
#Add code to stop when no new links occur and optimize the outer for loop
#for j in allHotels:
for contactAll in splitListAll: 
    if contactAll in conContact:
        conContact.extend(contactAll)
#       contactChk = contactAll
#       if (set(conContact) & set(contactChk)):
#           conContact = contactChk
#           contactChk[:] = [] #drop contactChk list
        conId = allHotels[countB]["autoid"]
    countB = countB+1

print "Printing the list of connected hotels..."
for final in collection.find({"autoid":conId}):
    print final

这是我用Python编写的一个代码。在这一个中,我尝试在for循环中执行线性搜索。到目前为止我遇到了一些错误,但在纠正后应该会有效。

我需要优化版本,因为班轮搜索时间复杂度很低。

我对此很新,所以欢迎任何其他改进代码的建议。

感谢。

1 个答案:

答案 0 :(得分:0)

任何Python内存中搜索问题的最简单答案是"使用dict"。 Dicts给出O(ln N)密钥访问速度,列表给出O(N)。

还要记住,您可以将Python对象放入尽可能多的dicts(或列表)中,并将其放入一个dict或list中。它们不会被复制。它只是一个参考。

所以必需品看起来像

for hotel in hotels:
   phones = hotel["phone_search"].split("|")
   for phone in phones:
       hotelsbyphone.setdefault(phone,[]).append(hotel)

在此循环结束时,hotelsbyphone["123456"]将是一个酒店对象列表,其中包含" 123456"作为他们的phone_search字符串之一。密钥编码功能是.setdefault(key, [])方法,如果密钥不在dict中,则初始化空列表,以便您可以附加到它。

一旦建立了这个索引,这将是快速的

try:
    hotels = hotelsbyphone[x]
    # and process a list of one or more hotels
except KeyError:
    # no hotels exist with that number

try ... except的替代方案,请测试if x in hotelsbyphone: