Как хранить результаты динамически сгенерированных форм в MongoDb? - PullRequest
10 голосов
/ 03 ноября 2011

Я новичок в MongoDB, но пытаюсь решить эту проблему:

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

Я пришел из типичного фона PHP / mySql и вижу некоторые проблемы при хранении этих данных вбаза данных mySql.Каждая форма может иметь любое количество полей всех типов.Мне нужно либо нормализовать мою БД в структуре EAV для хранения данных, либо динамически создать новую таблицу для каждой формы, либо сериализовать данные формы в столбцы TEXT (ick).

«Без схемы»"(или" динамическая схема ") природа MongoDb кажется идеальным решением моей проблемы, но мой n00b-iness оставляет меня неуверенным, с чего начать.

  1. Должны ли храниться результаты каждой пользовательской формыкак отдельные коллекции?
  2. Должен ли я иметь коллекцию "форм" и вставлять результаты в виде поддокументов для каждой формы?
  3. Есть ли другой, лучший способ?
  4. Является ли MongoDb действительно хорошим решением для этого, или я далеко от базы?

Чтобы еще раз сформулировать мою проблему: мне нужно хранить данные переменных и неизвестных структур в удобном для поиска и сортируемом виде.

Спасибо!

1 Ответ

17 голосов
/ 03 ноября 2011

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

Поскольку ваши формы являются переменными, но предопределенными (то есть каждая форма может отличаться, но формы определяются заранее в каком-то пользовательском интерфейсе администратора), я бы рекомендовал использовать две коллекции:

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

{ _id: ObjectId(...),
  name: "...",
  // other fields, for permissions, URL, etc
  fields: [
    { name: "username",
      type: "text",
      validation: { required: true, min: 1, max: null },
    },
    { name: "email",
      type: "text",
      validation: { required: true, min: 5, max: null, email: true },
    }
  ]
}

Это позволяет вам динамически создавать формы (вместе с некоторым серверным кодом) по мере необходимости для отображения в вашем приложении. Он также предоставляет информацию о том, что такое поля и какая проверка требуется для них, что вы можете использовать при отправке формы. Вам потребуется индекс для URL или любое другое поле, которое вы используете, чтобы определить, какую форму отображать при обслуживании веб-запросов.

Вторая коллекция, submissions или что-то еще, будет хранить отправленные данные для каждой формы. Документы будут выглядеть так:

{ _id: ObjectId(...),
  form: ObjectId(...), // the ObjectId of the record in "forms"
                       // that this is a submission on
  // other information here about the submitter:
  // IP address, browser, date and time, etc
  values: {
    username: "dcrosta",
    email: "dcrosta@awesomesite.com",
    //any other fields here
  }
}

Если вам нужно иметь возможность поиска по парам поле-значение (или просто по значениям) в отправленных формах, вариация этого использует массив для поля values, например:

{ ...
  values: [
    { name: "username", value: "dcrosta" },
    { name: "email", value: "dcrosta@awesomesite.com" }
  ]
}

Затем вы можете создать индекс в поле values и выполнить поиск:

// find "dcrosta" as username
db.submissions.find({values: {$elemMatch: {name: "username", value: "dcrosta"}}})

Или создайте индекс для "values.value" и выполните поиск:

// find "dcrosta" as value to any field
db.submissions.find({"values.value": "dcrosta"})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...