Как сохранить результаты из динамически создаваемых форм в MongoDb?

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

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

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

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

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

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

Спасибо!

Ответ 1

Я не буду хранить результаты в виде встроенных документов в документе 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: "[email protected]",
    //any other fields here
  }
}

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

{ ...
  values: [
    { name: "username", value: "dcrosta" },
    { name: "email", value: "[email protected]" }
  ]
}

Затем вы можете создать индекс в поле 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"})