2013-02-13 5 views
2

Я новичок в mongodb.Рекурсивный запрос?

Скажем, у меня есть «файловая система» иерархии в моей базе данных:

db.directories.save({ _id: "root", directories: ["src", "lib"], files: ["config.cfg"] }) 
db.directories.save({ _id: "src", directories: [], files: ["file1.js", "file2.js"] }) 
db.directories.save({ _id: "lib", directories: [], files: [] }) 

db.files.save({ _id: "config.cfg", size: 2310 }) 
db.files.save({ _id: "file1.js", size: 5039 }) 
db.files.save({ _id: "file2.js", size: 1299 }) 

Как бы я получить общий размер папки?

т.е. общий размер каталога «корневой» = общий размер файлов + общий размер подкаталогов

+0

Обычно вы бы спроектировать схему на основе запросов, которые вы хотите работать, а не наоборот. В текущей схеме нет способа сделать то, что вы хотите в одном запросе. –

+0

Какую схему вы бы предложили вместо этого? – Bart

ответ

9

Вопрос о том, что схема будет наилучшим образом соответствовать типу модели доступа вы описать ответ в некоторых примерах переговоры о том, как представляют собой иерархию в базе данных MongoDB/document.

Общим ответом, который работает для множества разных запросов, является то, где вы храните в каждом файле его имя, размер, прямой родительский элемент и массив всех его предков.

Это сделает ваши данные выборки:

db.files.save({ _id: "root"}) 
db.files.save({ _id: "src", parent: "root", ancestors: ["root"] }) 
db.files.save({ _id: "lib", parent: "root", ancestors: ["root"]}) 
db.files.save({ _id: "config.cfg", parent: "root", ancestors: ["root"], size: 2310 }) 
db.files.save({ _id: "file1.js", parent: "src", ancestors: ["root","src"], size: 5039 }) 
db.files.save({ _id: "file2.js", parent: "src", ancestors: ["root","src"], size: 1299 }) 

Теперь, если вы хотите запросить такие вещи, как «Файлы в этом каталоге» или «все файлы в этом каталоге (в том числе рекурсивно)» вы запрашиваете:

db.files.find({ parent: "root" }) // all files in /src directory 
db.files.find({ancestors: "root"}) // all files under /root directory tree 

Так как вам нужно использовать рамки агрегации, чтобы получить такие вещи, как сумма, запрос для размера папки будет:

db.files.aggregate([ 
     {$match:{ancestors:"src"}}, 
     {$group:{ 
      _id: "src", 
      total_size: {$sum:"$size"} 
      } 
     } 
]); 

Чтобы увидеть размер всех папок, которые находятся в корневой папке он будет:

db.files.aggregate([ 
     {$match:{ancestors:"root"}}, 
     {$group:{ 
      _id: "root", 
      total_size: {$sum:"$size"} 
      } 
     } 
]); 
+0

Ваш пример очень помог мне –

Смежные вопросы