#php #mongodb
#php #mongodb
Вопрос:
Сначала скажу, что я новичок в MongoDB и документоориентированных базах данных в целом.
После некоторых проблем со встроенными документами в mongodb (невозможно выбрать только вложенный документ (пример отдельного комментария в сообщении в блоге)), я переработал базу данных. Теперь у меня есть две коллекции, сообщения и комментарии (не совсем, для удобства использую пример из блога).
Пример — документ коллекции posts:
Массив {
'_id' : MongoId,
'title' : 'Something',
'body' : 'Something awesome'
}
Пример — комментарии к документу:
Массив {
'_id' : MongoId,
'postId' : MongoId,
'userId' : MongoId,
'commentId' : 33,
'comment' : 'Punch the punch line!'
}
Как вы можете видеть, у меня есть несколько документов с комментариями (как я уже говорил ранее, я хочу иметь возможность выбирать один комментарий, а не их массив).
Мой план таков: я хочу выбрать один комментарий из коллекции, используя postID и commentId (commentId — уникальное значение только среди комментариев с одинаковым postID). О, и commentId должен быть int, чтобы я мог использовать это значение для вычисления следующего и предыдущих документов, что-то вроде номера «orderWith».
Теперь я могу получить комментарий, подобный этому:
URI: mongo.php?post=4de526b67cdfa94f0f000000amp;comment=4
Код: $comment = $collection->findOne(массив(«postID» => $theObjId, «commentId» => (int)$commentId));
У меня есть несколько вопросов.
- Я все делаю правильно?
- Каков наилучший способ сгенерировать такой идентификатор комментария?
- Каков наилучший способ убедиться, что идентификатор комментария уникален среди комментариев с одинаковым идентификатором postID (upsert?)?
- Как работать с параллельными запросами?
Ответ №1:
Я все делаю правильно?
Это действительно сложный вопрос. Работает ли это? Соответствует ли он вашим потребностям в производительности, удобно ли вам его поддерживать?
В MongoDB нет никакого понятия «нормализации» или «единственного верного способа». Вы моделируете свои данные таким образом, который подходит именно вам.
Каков наилучший способ сгенерировать такой идентификатор комментария? Каков наилучший способ убедиться, что идентификатор комментария уникален среди комментариев с одинаковым идентификатором postID (upsert?)?
Это действительно сложная проблема. Если вы хотите генерировать идентификаторы монотонно возрастающих целых чисел (например, автоинкремент), то вам нужен центральный орган для генерации этих целых чисел. Это, как правило, не очень хорошо масштабируется.
Обычно предлагаемый метод заключается в использовании идентификатора объекта / MongoId. Это даст вам уникальный идентификатор.
Однако вам действительно нужно целое число. Итак, взгляните на findAndModify . Вы можете сохранить «last_comment_id» в своем сообщении, а затем обновить его при создании нового комментария.
Как работать с параллельными запросами?
Почему параллельные запросы могут быть проблемой? Два читателя должны иметь доступ к одним и тем же данным.
Вы беспокоитесь о создании одновременных комментариев? Затем посмотрите документы по поиску и изменению.
Комментарии:
1. @Gates и @Earlz Спасибо за вашу помощь, но в конце я собираюсь использовать ref с MongoId.
2. Вау… Я не знал, что у комментариев есть 5-минутное окно для редактирования : ( Вот остальная часть предыдущего. @Gates и @Earlz Спасибо за вашу помощь, но в конце я собираюсь использовать ref с MongoId. В документе Post будет массив mongoids, ссылающихся на комментарии, в отдельной коллекции. Ключи массива Mongo с «автоматическим увеличением» будут использоваться как целые числа. С этим, я полагаю, я смогу сортировать и выбирать предыдущий и следующий элемент.
3. Хм, я не понял, почему вы храните комментарии в отдельной коллекции. Это не имеет никакого смысла с точки зрения, ориентированной на документ (нереляционной), и каким-то образом противоречит идее, лежащей в основе концепции mongodb. Особенно не имеет никакого смысла ссылаться на них с помощью массива MongoIds в коллекции ваших сообщений, что приводит к потере производительности и ужасной оргии с обслуживанием. Вместо того, чтобы тратить энергию на дальнейшие редизайны БД… возможно, было бы хорошей идеей предложить другой вопрос, касающийся вашей «проблемы» с внедрением. Я полагаю, что есть подходящие решения … 😉
4. @proximus Одна из самых больших проблем, с которой я сталкиваюсь, заключается в том, что mongodb не может выбрать и вернуть ТОЛЬКО ОДИН встроенный массив / документ из обычного документа; Вместо этого мне нужно получить весь документ со встроенным массивом, по крайней мере, с 500 элементами (которые, кстати, не являются маленькими простыми комментариями.) В любом случае, судя по всему, я пока буду использовать mysql. По крайней мере, до этого jira.mongodb.org/browse/SERVER-142 становится доступным. Спасибо за вашу помощь 🙂
5. @Marko Возможно, я неправильно понял ваше беспокойство… но разве это не распространяется на извлечение отдельных встроенных массивов / документов? Например. Ваши комментарии, связанные с сообщением, хранятся в виде массива комментариев внутри вашего документа post, и каждый вложенный комментарий содержит уникальный ключ (например, ObjectId для целей сортировки), вы могли бы сделать:
db.posts.findOne( { '_id' : ObjectId('...'), 'comments.id' : ObjectId('...') }, { comments : 1 } );
(примечание { comments: 1 } , равный$fields
параметру в PHPMongoCollection::find()
)
Ответ №2:
Я не знаю, позволит ли вам это сделать общая картина, но вот как я бы это сделал.
У меня был бы массив комментариев, содержащихся внутри каждого сообщения. Это означает, что объединения не требуются. В вашем случае нормализация комментариев не дает никакой пользы. Я бы заменил CommentID
на CreatedAt
в качестве времени создания.
Это позволит вам иметь простую модель данных для работы, а также возможность сортировать их.