Запрос к MongoDB для получения вложенного массива с пропуском/ограничением по диапазону ключей вложенных объектов в Django с помощью pymongo
Я изучаю Django с помощью pymongo.
У меня есть коллекция MongoDB, в которой я храню некоторые слова и их встречаемость по годам в некоторых книгах.
Документы хранятся в MongoDB в следующем формате:
{
"_id":{
"$oid":"625c51eec27c99b793074501"
},
"word":"entropy",
"occurrence":13,
"year":{
"1942":[
{
"book":{
"$oid":"625c51eec27c99b7930744f9"
},
"number":8,
"sentence":[
1,
288,
322,
1237,
2570,
2585,
2617,
2634
]
}
],
"1947":[
{
"book":{
"$oid":"625c5280c27c99b793077042"
},
"number":5,
"sentence":[
377,
2108,
2771,
3467,
3502
]
}
]
}
}
Теперь я хочу получить список предложений с skip и limit (и соответствующий id книги), запрошенный по _id и для определенного year диапазона.
Например,
- I want to fetch an array where each row will be a dictionary containing 'year', 'book' and 'sentence'.
- The array will be queried by the _id and year range.
- A skip and limit will be applied on the sentence list
Возможна ли такая задача с использованием Django и pymongo? Если да, то какой метод самый быстрый?
На данный момент я сделал следующее:
search= {'$and': [{"_id": word_id_obj, "year.1942": {"$exists": 1}}]}
datalist= []
word_docs= wordcollec.find(search, {'year': 1, '_id': 0}).skip(1).limit(5)
sentlist['recordsFiltered']+= wordcollec.count_documents(search)
for b in word_docs:
year_data= b['year'][1942]
for by in year_data:
i= i+1
this_word= {'serial': i, 'year': cyear, 'book': str(by['book'])}
datalist.append(this_word)
Но очевидно, что это не дает желаемого результата, поскольку skip и limit применяются к объекту корневого документа. Также параметр year имеет фиксированное значение и не имеет диапазона.
Похоже, что использование '$slice' - это вариант. Но я не могу понять этого.
Спасибо, что дочитали до конца. И многое другое, если вы сможете пролить свет.
Вот один из способов:
... получить массив, где каждая строка будет словарем содержащий 'год', 'книгу' и 'предложение'.
db.collection.aggregate([
{ "$set": { "designWorkAround": { "$objectToArray": "$year" } } },
{ "$set": {
"designWorkAround": {
"$map": {
"input": "$designWorkAround",
"as": "yearArray",
"in": {
"year": "$$yearArray.k",
"books": {
"$map": {
"input": "$$yearArray.v",
"as": "bookArray",
"in": {
"bookId": "$$bookArray.book",
"number": "$$bookArray.number",
"sentence": "$$bookArray.sentence"
}
}
}
}
}
}
}
},
{ "$unwind": "$designWorkAround" },
{ "$unwind": "$designWorkAround.books" },
{ "$project": {
"_id": 0,
"year": "$designWorkAround.year",
"book": "$designWorkAround.books.bookId",
"sentence": "$designWorkAround.books.sentence"
}
}
])
Попробуйте на mongoplayground.net.
Я не знаю всех генераций данных и запросов, которые вам могут понадобиться, но я бы, вероятно, переработал коллекцию и сделал бы что-то вроде одного документа на книгу со всеми соответствующими полями в документе. Это упростит и сделает более эффективными запросы, индексирование и т.д.