В данном примере мы не фильтруем и не агрегируем; мы делаем большое find()
, а затем мы хотим все имена полей. Там также нет проекции. Если предположить, что мы все равно перетаскиваем все данные, пусть клиентская часть сделает всю работу. Вот что захватит уникальные имена полей, в том числе через массивы, и подсчитает количество уникальных имен полей:
r = [
{"_id":0, "A":"A", "data":[
{"Y":2020,"day":3,"clicks":12},
{"Y":2020,"day":4,"clicks":192}
]} ,
{"_id":1, "B":{"foo":"bar"}, "data":[
{"Y":2020,"day":3,"clicks":888,"corn":"dog"},
{"Y":2020,"day":4,"clicks":999,"zing":"zap"}
]} ,
{"_id":2, "B":{"foo":"bit"} },
{"_id":3, "B":{"fin":"bar"} }
]
coll.insert(r)
fieldNames = {}
def addFldName(s):
if s not in fieldNames:
fieldNames[s] = 0
fieldNames[s] += 1
def process(path, v):
addFldName(path)
if("dict" == v.__class__.__name__):
walkMap(path, v)
elif("list" == v.__class__.__name__):
walkList(path, v)
def walkMap(path, doc):
dot = "" if path is "" else "."
for k, v in doc.iteritems():
s = path + dot + k
process(s, v)
def walkList(path, array):
dot = "" if path is "" else "."
for n in range(0,len(array)):
s = path + dot + str(n)
process(s, array[n])
for doc in coll.find():
walkMap("", doc)
print(fieldNames)
{u'A': 1, u'data.1.clicks': 2, u'B': 3, u'data.0': 2, u'data.1': 2, u'data.0.Y': 2, u'data.1.zing': 1, u'data.0.day': 2, u'B.fin': 1, u'B.foo': 2, u'data.1.Y': 2, u'_id': 4, u'data': 2, u'data.0.corn': 1, u'data.0.clicks': 2, u'data.1.day': 2}
Это немного странно, но да, data.0.clicks
уникально и отображается в 2 документа.