Как сохранить файл JSON с помощью GridFs - PullRequest
4 голосов
/ 01 апреля 2020

У меня огромный набор данных, я использую схемы mon goose, и каждый элемент данных выглядит следующим образом:

    {
      field1: “>HWI-ST700660_96:2:1101:1455:2154#5@0/1”: 
      field2: “GAA…..GAATG”

    }

Источник: Чтение файла FASTA

Как видите, отдельные элементы простые и маленькие, но их огромное количество! Вместе они будут превышать 200 МБ.

Проблема в следующем: Я не могу сохранить его в mon go, поскольку он слишком большой (> 200 МБ) .

Я нашел GridFs, тем не менее,

  • Все найденные мной материалы рассказывают о загрузке изображений и видео;

  • Они не говорят, как я все еще мог бы использовать возможность схемы mon goose;

  • Примеры, которые я видел до сих пор, не сохраняют данные в пути, определенные пользователем, как мы делаем с mon goose.

В самом простом сценарии: как я могу сохранить файл JSON, используя GridFS, или любое подобное решение, как я делаю с маленьким JSON файлы. Каковы плюсы и минусы этого подхода по сравнению с другими подходами, если таковые имеются? Считаете ли вы мой подход обоснованным? Я имею в виду тот, который я упомянул здесь, используя дерево JSON файлов и populate позже, это работает!

В качестве примера сохранения файла JSON с использованием mon goose:

Model.create([        
          {
          field1: “>HWI-ST700660_96:2:1101:1455:2154#5@0/1”: 
          field2: “GAA…..GAATG”

        }, 
        {
          field1: “>HWI-ST700660_96:2:1101:1455:2154#5@0/1”: 
          field2: “GAA…..GAATG”

        }]);

Здесь я только что сохранил двухэлементный файл JSON, я не могу сделать это с огромным, мне нужно разбить на более мелкие кусочки (например, 1%) и создать дерево только что упомянул, по крайней мере, это было мое решение.

Боюсь, я могу заново изобретать колеса. Я мог бы сохранить эти файлы независимо, и это работает, но мне нужно, чтобы они были коррелированными, потому что они принадлежат одному и тому же файлу, как маленькие куски изображения принадлежат одному и тому же изображению.

Боюсь, я возможно, заново изобретаем колеса.

Текущее решение

Это мое текущее решение, используя мои собственные идеи! Обратите внимание, что я упоминаю здесь просто для любопытства , он не использует GridFS, поэтому я все еще открыт для предложений по использованию GridFS. Он использует только JSON файлов и разбивает документ на более мелкие, на уровне иерархии. Это дерево, и я просто хочу листья в растворе.

enter image description here

Я решил проблему , используя эту диаграмму тем не менее, я хочу, чтобы в учебных целях, см. , если возможно сделать то же самое, используя GridFS .

Дискуссия

Мой первый подход состоял в том, чтобы сохранить их как subdo c: это не удалось! затем я попытался сохранить только их идентификаторы, их идентификаторы соответствуют 35% всего фрагмента, и он больше 16 МБ: не удалось! затем я решил создать фиктивный документ, просто чтобы сохранить идентификаторы, и хранить только идентификатор фиктивных документов: успехов!

Ответы [ 2 ]

1 голос
/ 13 апреля 2020

Я нашел лучший способ решить эту проблему, чем тот, который я реализовал, тот, что в описании вопроса. Мне просто нужно использовать виртуалы!

Сначала я подумал, что использование ForEach для добавления дополнительного элемента в файл Fasta будет медленным, это не , это довольно быстро!

Я могу сделать что-то подобное для каждого файла Fasta:

{
  Parentid: { type: mongoose.Schema.Types.ObjectId, ref: "Fasta" }//add this new line with its parent id
  field1: “>HWI-ST700660_96:2:1101:1455:2154#5@0/1”: 
  field2: “GAA…..GAATG”

}

Затем что-то вроде этого:

FastaSchema.virtual("healthy", {
  ref: "FastaElement",
  localField: "_id",
  foreignField: "parent",
  justOne: false,
});

Наконец заполняется:

  Fasta.find({ _id: ObjectId("5e93b9b504e75e5310a43f46") })
    .populate("healthy")
    .exec(function (error, result) {          
      res.json(result);
    });

И волхвы c сделаны, никаких проблем с перегрузкой поддокумента! Заполнение, примененное к Virtual, довольно быстро и не вызывает перегрузок! Я этого не делал, но было бы интересно сравнить с обычным населением; однако этот подход имеет то преимущество, что нет необходимости создавать скрытые do c для хранения идентификаторов.

Я потерял дар речи от этого простого решения, которое возникло, когда я отвечал на другой вопрос здесь, и оно только что появилось!

Благодаря мон goose!

1 голос
/ 04 апреля 2020

Весьма вероятно, что не стоит хранить данные в Mon go с использованием GridFS.

Двоичные данные никогда не принадлежат базе данных, но если данные небольшие, то преимущества их размещения в базе данных (возможность запроса) перевешивает недостатки (медленная загрузка сервера).

В этом случае похоже, что вы хотите хранить данные документа (JSON) в GridFS. Вы можете сделать это и хранить его так же, как любые другие двоичные данные. Данные, однако, будут непрозрачными. Вы не можете запросить JSON данные, хранящиеся в документе GridFS, только метаданные файла.

Запрос больших данных

Поскольку вы упомянули, что хотите запросить данные, вы должны проверить формат вашего данные. Если ваши данные в формате, указанном в примере, то кажется, что нет необходимости в сложных запросах, только сопоставление строк. Таким образом, есть несколько вариантов.

Случай 1: большие данные, несколько точек

Если у вас не много наборов данных (пары field1 и field2), но данные для каждого из них большой (field2 содержит много байтов), храните их в другом месте и храните только ссылку на это. Простым решением было бы сохранить данные (ранее field2) в текстовом файле на Amazon S3 и затем сохранить ссылку. например,

{
  field1: “>HWI-ST700660_96:2:1101:1455:2154#5@0/1”,
  field2link: "https://my-bucket.s3.us-west-2.amazonaws.com/puppy.png"
}

Случай 2: небольшие данные, много точек

Если каждый ваш набор данных мал (менее 16 МБ), но имеется много наборов данных, сохраните ваши данные в MongoDB ( без GridFS).

Особенности

В вашем случае данные достаточно велики, и их хранение с использованием GridFS нежелательно.

Этот ответ дает ориентир по направлению к основанию. Похоже, что эталонный тест указывает на то, что время поиска более или менее прямо пропорционально размеру файла. При такой же настройке для извлечения документа из базы данных потребуется 80 секунд.

Возможные оптимизации

Размер порции по умолчанию в GridFS составляет 255 КиБ. Вы можете сократить время доступа к большим файлам, увеличив максимальный размер чанка (16 МБ). Если размер порции является единственным узким местом, то использование размера порции 16 МБ сократит время поиска с 80 секунд до 1,3 секунд (80 / (16 МБ / 255 КБ) = 1,3). Это можно сделать при инициализации корзины GridFS.

new GridFSBucket(db, {chunkSizeBytes: 16000000})

Лучшей стратегией было бы сохранить единственное имя файла в Mon go и вместо этого извлечь файл из файловой системы.

Другие недостатки

Другой возможный недостаток хранения двоичных данных в Mon go исходит от this site : «Если двоичные данные большие, то загрузка двоичных данных данные в память могут привести к тому, что часто используемые текстовые (структурированные данные) документы будут вытеснены из памяти, или, в более общем случае, рабочий набор может не помещаться в ОЗУ. Это может отрицательно повлиять на производительность базы данных ». [ 1 ]

Пример

Сохранение файла в GridFS, адаптированное из учебника Mon go GridFS

const uri = 'mongodb://localhost:27017/test';

mongodb.MongoClient.connect(uri, (error, db) => {
  const bucket = new mongodb.GridFSBucket(db);

  fs.createReadStream('./fasta-data.json')
    .pipe(bucket.openUploadStream('fasta-data.json'))
    .on('finish', () => console.log('done!'))
  ;
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...