Ответы пользователя по тегу MongoDB
  • Как оптимизировать запрос mongodb?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Сделать индивидуальный индекс для тегов
    schema.index( { url: 1 } )
    schema.index( { tags: 1 }, {sparse: true} )
    schema.index( { catalog: 1 } )


    Склеить теги в одно поле, построить по нему индекс.

    RTFM mongoosejs.com/docs/guide.html#indexes

    Сортировка занимает много времени, т.к. используется индекс catalog_1_tags_1 для условия. Разумеется сортировать по нему не получится.
    Попробуйте сортировать так:
    { $sort: { catalog: 1, tags: 1 } },
    Ответ написан
  • Существуют ли npm для морфологического разбора слов?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    https://www.npmjs.com/package/enchant для Enchant вы можете поставить русские словари.
    https://docs.mongodb.com/manual/text-search/ Можно все собрать в одну строку и использовать текстовый индекс, он не так уж и плох.

    Если вы хотите сделать действительно хороший поиск смотрите в сторону elasticsearch, solr, sphinx.
    Ответ написан
    Комментировать
  • Что произойдет, когда база данных MongoDB станет слишком большой?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    1. Процесс упадет.
    2. Система не загрузится, если нет свободного места на диске.

    Для того, чтобы избежать такую проблему нужно научиться делать шардинг. Поэтому читаем:
    1. Пофиг, что MySQL, важно понять принцип https://ruhighload.com/post/%D0%A8%D0%B0%D1%80%D0%...
    2. Старая версия (она подробнее) https://docs.mongodb.com/v3.0/core/sharding-introd...
    3. Новая https://docs.mongodb.com/manual/sharding/
    Ответ написан
    2 комментария
  • Для чего идеальна MongoDb? Примеры приложений, где монга будет лучше mysql?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Я работаю с MongoDB на протяжении уже 4х лет. Имеется ряд проектов, созданных как с использованием этой БД, так и использованием классических RDBMS.
    MongoDB это не MySQL и не PostgreSQL. Большинство людей пытается сравнить оба типа баз данных, но это абсолютно глупо и неприемлемо. Это все равно что сравнивать врачей и инженеров.
    MongoDB подойдет там, где нужна гибкость структуры и большие объемы данных. Например хранение истории болезни пациентов в масштабе страны. Каждая карточка может быть разного типа со множеством полей. И их могут быть триллионы. Для классических реляционных БД это выливается в весьма нетривиальную задачу горизонтального масштабирования, которая в MySQL решается через перенастройку сервера, а в PostgreSQL через специальную промежуточную таблицу. Горизонтальный рост и ввод новых узлов кластера сопряжен с большими трудностями и плохо автоматизируется для реляционных БД.
    Еще классические БД очень плохо работают со смешанной нагрузкой, когда у вас запись/чтение примерно 1:1 и данных очень много. Это вызывает непрерывное перестроение индексов и их использование больше мешает. Это тот тип нагрузки, при которой InnoDB частенько повреждается без возможности восстановления или что вызывает значительный простой на реорганизацию структур данных.
    Также существует очень много задач, для которых использование MongoDB исключительно неприемлемо. Если вам необходимо работать с нормализованными данными - используйте реляционные БД. Если нужна мощная аналитика - колоночные. Разумеется, каждая из этих опций имеет свою цену.
    На рынке нет универсального решения. Каждое заточено под свои задачи.
    Ответ написан
    2 комментария
  • Python MongoDB Можно ли присоединиться к локальному файлу в папке проекта?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Просто создать локальный файл не получится, MongoDB это не SQLite, у нее достаточно много файлов.
    Наиболее разумно использовать внешнюю папку для Docker контейнера.
    Но ничего вам не мешает запускать MongoDB с внешним файлом конфигурации, в котором указан путь к своей папке.
    Ответ написан
    Комментировать
  • Как обновить запись в mongodb учитывая уникальный параметр?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Вам нужно делать update с $addToSet.

    db.getCollection('t1').update(
    {
        _id: ObjectId("599aa4467745ffb9644da8eb"),
        "series.id": "58e52c4e89673a7a83438f1c",
    },
        
    { $addToSet: {
            'series.$.letters': {
                "id" : "1bki584500r0trtyie7700002",
                        "sented_at" : [ 
                            "2017-08-23 16:46"
                        ]
            } 
        }
    }
    )


    И вместо 'sented_at' использовать 'sent_at'.
    Прошедшая форма глагола send это sent.
    Ответ написан
    Комментировать
  • Почему я получаю проблему нарушения уникальности в MongoDB?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Потому что MongoDB при построении текстового индекса разбивает строку на слова, затем удаляет так называемые стоп-слова и может их нормализовывать.
    Допустим у вас есть следующие 2 документа.
    {text: "Два красивых яблока" }
    {text: "Много яблок" }


    Когда будет сформирован текстовый индекс, произойдет следующее. На самом деле все происходит немного иначе, в целом процесс таков.

    Строка токенизируется на слова:
    "Два красивых яблока" → ["Два", "красивых", "яблока"]
    "Много яблок" →  ["Много", "яблок"]


    Далее слова нормализуются

    ["Два", "красивых", "яблока"] → ["два", "красивый", "яблоко"]
    ["Много", "яблок"] →  ["много", "яблоко"]


    Теперь начинается формирование словаря. Каждому слову начинаем присваивать номера.

    ["два", "красивый", "яблоко"] → [1, 2, 3], и словарь [1↔"два", 2↔"красивый", 3↔"яблоко"]
    ["много", "яблоко"]  →  [4, 3], и в словарь [1↔"два", 2↔"красивый", 3↔"яблоко", 4↔"много"]


    Т.е. получаем следующий набор в индексе
    [1→1, 2→1, 3→1]
    [4→2, 3→2]

    Т.к. это индекс, то разбиения объединяются в общий указатель
    1→1, 
    2→1, 
    3→1, 
    4→2 
    3→2


    А теперь смотрите, у нас индес объявлен уникальным, но указатели на записи повторяются, значит указатель не уникальный.
    Поэтому и возникает ошибка.

    Чтобы решить проблему, нужно создать 2 индекса.
    Первый - текстовый, но без требования уникальности.
    Второй - уникальный, на основе бинарного дерева.
    Ответ написан
    2 комментария
  • Как закрыть доступ из-вне к mongodb?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Вы занимаетесь какой-то ерундой. Нет ничего страшного в том, что MongoDB слушает какой-то интерфейс.
    Обычно это решается настройкой фаервола.
    То, на что вам нужно обратить внимание, это опции авторизации
    https://docs.mongodb.com/manual/reference/configur...
    Рано или поздно вам прийдется выйти за рамки локалхоста и прийдется настраивать авторизацию.
    Ответ написан
    Комментировать
  • Как лучше осуществлять поиск для создания переписок в MongoDb?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Вы можете использовать populate(), он эффективно сделает это за вас.
    Ответ написан
    Комментировать
  • Как сделать частичный поиск в mongodb?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    У MongoDB сейчас поиском не все хорошо, особенно на русском языке. Я пытался пофиксить их список стоп-слов, но есть внутренняя проблема с версионированием индексов. Пока ее не решат, подвижек в области поиска по словам не стоит ожидать.
    Поиск по части слова можно реализовать с использованием регулярных выражений, но это будет не очень эффективно и медленно. al_gon все правильно говорит, для поиска по тексту нужны решения, которые специально заточены под поиск.
    Ответ написан
    Комментировать
  • Как получить поле, в котором произошла ошибка валидации?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Валидация ошибок в постхуке не очень хорошая практика.
    Посмотрите тут mongoosejs.com/docs/validation.html

    var breakfastSchema = new Schema({
          eggs: {
            type: Number,
            min: [6, 'Too few eggs'],
            max: 12
          },
          bacon: {
            type: Number,
            required: [true, 'Why no bacon?'] // здесь мы устанавливаем нужное сообщение
          },
          drink: {
            type: String,
            enum: ['Coffee', 'Tea'],
            required: function() {
              return this.bacon > 3;
            }
          }
        });
        var Breakfast = db.model('Breakfast', breakfastSchema);
    
        var badBreakfast = new Breakfast({
          eggs: 2,
          bacon: 0,
          drink: 'Milk'
        });
        var error = badBreakfast.validateSync(); // а теперь проверим перед тем, как сохранить
        console.log(error); // дампнем ошибку


    Правильнее проверять поля до момента вызова сохранения данных. Например вы можете втихую через аякс отправлять данные формы и проверять их на валидность подсвечивая элементы на форме.
    Ответ написан
    1 комментарий
  • Складской учет на Mongo?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Не следует использовать MongoDB для такого рода решений.
    Складской учет требует огромного количества отчетов и разного рода справочных данных.
    Реляционная модель подходит для этого гораздо лучше.
    Ответ написан
    Комментировать
  • Как исправить следующую ошибку MongoDB?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Скорее всего происходит из-за старой версии MongoDB.
    Метод listCollections появился начиная с версии 3.0.0.
    Я рекомендую вам использовать последнюю версию MongoDB и WiredTiger. Там решен ряд проблем с местом и производительность выше старого движка MMAPv1.
    Ответ написан
  • MongoDB тест - что выдает команда Object.keys(db.collection.findOne())?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Я не совсем понял, где несоответствие?

    Например такой запуск для коллекции
    Object.keys(db.getCollection('topics').findOne())
    Выдаст список ключей
    /* 1 */
    [
        "_id",
        "user",
        "title",
        "slug",
        "body",
        "category",
        "spam",
        "tags",
        "subscribers",
        "updated",
        "created",
        "__v",
        "private"
    ]


    Если вы получаете следующее
    TypeError: can't convert null to object :
    @(shell):1:1

    это значит, что вы забыли указать имя коллекции.
    Ответ написан
    Комментировать
  • Как записать json в mongodb?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Почитайте документацию
    mongodb.github.io/mongo-java-driver/2.13/getting-s...
    Ответ написан
    Комментировать
  • Несколько вопросов о mongodb?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Я работаю с MongoDB уже более 3 лет, поэтому буду рассказывать и давать советы опираясь на личный опыт эксплуатации.

    Получается, что нас всю жизнь учили данные нормализовывать и объясняли, почему это хорошо, а теперь все с точностью наоборот?

    Не совсем. Вас учили работать только с одной разновидностью баз данных - реляционной. Теперь вы увидели, что бывают еще и другие, документ-ориентированные. Разумеется, в каждой разновидности будут свои подходы к хранению и организации данных.
    Это не хорошо и не плохо, это иначе.
    Несомненно, ажиотаж вокруг термина NoSQL существует. И на то есть причины, в основном то, что данных действительно стало больше. Информационная энтропия увеличивается и ее все сложнее укладывать в рамки реляционных баз данных. Здесь можно долго рассуждать, но могу с уверенностью сказать, что сейчас появился спрос на такие хранилища, в которых структуру нужно менять более быстро, чем это могут позволить реляционные базы данных.

    Объясните, пожалуйста, на пальцах, правильно ли я все понимаю?

    По большей части вы правы. Это денормализованные данные, но с определенными моментами. Я покажу вам их на вашем же примере.

    Как в монго при этом обновлять данные, которые хранятся в каждом документе?


    Это реализуется с помощью банальных обновлений.
    Например, если у меня есть коллекция с книгами, в которой мне нужно обновить авторов.

    Типичная запись в ней выглядит так
    {
        "_id" : ObjectId("5801aa17964c6b2a050041a7"),
        "title" : "New Book",
        "authors" : [ 
            {
                "_id" : ObjectId("5801aa0f964c6b26030041a9"),
                "firstName" : "Phil",
                "lastName" : "Tkachev"
            }
        ]
    }


    И я хочу заменить имя в тех книгах, в которых я - автор, то мой запрос будет выглядеть так:

    db.getCollection('book').update(
     {'authors._id':ObjectId("5801aa0f964c6b26030041a9")}, 
     {$set: {'authors.$.firstName': 'Philipp'}  }, 
     {multi: true } 
    )


    Здесь есть ряд разных сценариев, просто почитайте документацию. В ней все неплохо расписано.

    Приемлемо ли в монго денормализовывать данные, чтобы хранить данные в отдельной коллекции, и обращаться к ним отдельным запросом (ведь джоинов там нет)?


    Есть ряд случаев, когда так и делают. Например есть разного рода ORM, тот же Mongoose, который так и делает.

    И принято ли так работать?


    И да, и нет. Когда вы работаете с такого рода базой данных, вам нужно подходить к организации данных исходя из решаемой проблемы, отталкиваться от проекта будущего приложения или решения задачи.
    Вам просто нужно ответить на вопрос, что дешевле, запросить документ по ключу или обновить запись внутри документов.
    Взять к примеру, ваш сайт, в котором есть новости и их авторы. Новости могут читать миллионы, а значит при обращении к каждой новости нужно будет делать подзапрос на информацию о каждом авторе. Т.е. вместо одного запроса, при просмотре новости, нужно будет делать 2. А если показывать список из 100 новостей? Будете делать 100 вторичных запросов? Нет, это тоже неправильно. Нужно будет получить список новостей, в коде приложения собрать идентификаторы авторов, сделать второй подзапрос, получить информацию об авторах, затем объединить ее с уже полученным списком статей. Это немного усложнит ваше приложение, но тоже позволит сэкономить ресурсы. Если вы встроите авторов внутрь статьи, это позволит вам обойтись одним запросом к базе, хоть на просмотр, хоть на список новостей. С другой стороны вам прийдется подумать об обновлении информации об авторе. Но, т.к. такая информация меняется сравнительно редко, то есть смысл встраивания.

    Что делать, если изменилась структура данных, если структуры то и нет?


    Здесь все просто. Когда вы разрабатываете свое приложение, вы изначально закладываете в него обработку изменений. Например, вы можете добавить поле версии документа, в котором храните номер версии структуры и реагировать на ее изменение в коде. Либо вы можете просто писать приложение таким образом, что оно автоматически будет конвертировать структуру из старой в новую при первом обращении.

    По дизайну вашего приложения.
    Судя по первичным данным, у вас новостной сайт.
    Логично было бы его представить в следующем виде.

    Коллекция новостей:

    {
    	_id: 'MongoId',
    	title: '',
    	body: '',
    	author: {
    		_id: 'идентификатор пользователя',
    		name: 'Имя пользователя',
    		subscribers: 'Количество подписчиков'
    	}
    }


    Автор является неполной копией данных о пользователе. Это поможет сэкономить место и позволит избежать ненужных запросов.

    Коллекция пользователей:

    {
    	_id: 'MongoId',
    	name: 'Имя пользователя',
    	email: '',
    	roles: ['user', 'author', 'admin'],
    	subscribers: 'Number'
    }


    Список ролей может опеределять уровень доступных возможностей. Его легко изменить, можно легко найти авторов или админов.

    Коллекция подписок:

    {
    	initiator: {
    		_id: 'идентификатор пользователя, который инициировал подписку',
    		name: 'Имя пользователя'
    	},
    	target: {
    		_id: 'идентификатор автора',
    		name: 'Имя пользователя'
    	},
    	date: 'ISODate',
    	confirmed: 'bool'
    }


    Здесь вы можете подстроить, как список подписок, так и список подписчиков одним запросом.
    Ответ написан
    1 комментарий
  • Как сделать шардирование уже существующей базы в Mongo?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    0. Смириться, что будет некоторый простой и прийдется потратить кучу бабла.
    1. Рассмотреть существующую базу и определиться с ключами для шардинга.
    2. Подготовить код вашего приложения к ипользованию в реплике.
    3. Преобразовать текущую базу в реплицирующийся набор.
    4. Подготовить ваше приложение к работе с шардингом, оно должно работать только с балансировщиком и ни в коем случае не с шардом.
    5. Преобразовать реплику в кластер.

    В Монге каждый шард содержит реплику в себе.
    Ответ написан
    Комментировать