forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   Общее (http://forum.boolean.name/forumdisplay.php?f=139)
-   -   MongoDB (http://forum.boolean.name/showthread.php?t=18271)

pax 18.06.2013 14:02

MongoDB
 
Наверное буду время от времени задавать по ней вопросы...

Первый вопрос: Как оптимальнее перезаписать поле у всех записей таблицы? Хочу сбросить счетчик начисленного за неделю или за день опыта. Вообще если есть интересные мысли по организации такого топа то тоже прошу высказывать.

Заранее спасибо!

moka 18.06.2013 15:12

Ответ: MongoDB
 
Цитата:

Сообщение от pax (Сообщение 261628)
Наверное буду время от времени задавать по ней вопросы...

Какой драйвер используешь (язык)?

Цитата:

Сообщение от pax (Сообщение 261628)
Первый вопрос: Как оптимальнее перезаписать поле у всех записей таблицы? Хочу сбросить счетчик начисленного за неделю или за день опыта.

PHP код:

db.characters.update({ }, { $set: { experience} }, { multitrue }); 

Это примениться ко всем персонажам в бд. Установит experience на нуль. multi - нужен чтобы сообщить бд чтобы обновил все записи подходящие под фильр (в данном случае все т.к. фильтр пуст). По стандарту без multi обновляется только первая найденная запись.

Цитата:

Сообщение от pax (Сообщение 261628)
Вообще если есть интересные мысли по организации такого топа то тоже прошу высказывать.

На самом деле нам нужен раздел на форуме "Базы Данных", который будет покрывать все бд. Т.к. и по SQL'у было не мало вопросов.

И раздел "Web" не подходящий имхо, т.к. тут бд как угодно можно юзать.

ЗЫ, сам юзаю mongodb для проекта сейчас (по работе), используем 2dsphere индексацию для гео-кординат, крутая штука.

Советую также изучить как работают индексы, и тестировать запросы с использованием .explain() метода, чтобы посмотреть сколько времени запрос занял, какие индексы юзает и сколько листает и выдаёт записей.

pax 18.06.2013 15:36

Ответ: MongoDB
 
Спасибо, сделал так же за исключением первого условия. Передам пустой массив. Язык PHP но это роли не играет особой. Про explain спасибо, возьму на заметку.

moka 18.06.2013 16:26

Ответ: MongoDB
 
Для оптимизации, проиндексируй collection по experience полю.
Далее в запросе можешь фильтровать:
PHP код:

db.characters.update({ experience: { $gt} }, { $set: { experience} }, { multitrue }); 

Таким образом будут пролистываться только те документы, которые имеют какой либо опыт.
Для того чтобы убедиться в индексе, пропиши:
PHP код:

db.characters.find({ experience: { $gt} }).explain(); 

Должен указать какой индекс использовал, и сколько объектов пролистал (nscanned).


Далее попробуй так:
PHP код:

db.characters.find({ experience: { $gt} }).hint({ $natural}).explain(); 

Используя .hint({ $natural: 1 }) query проигнорирует какие либо индексы, и покажет данные запроса без индексации, разница должна быть на лицо.

pax 18.06.2013 16:36

Ответ: MongoDB
 
Индекс там уже есть, а вот условие первое я значит зря убрал)

moka 18.06.2013 16:43

Ответ: MongoDB
 
Учти что если в фильтре больше одного условия, то индексы не совмещаются, бд выберет тот что считает наиболее подходящий. Можно иметь compound index, который совмещает разные поля (последовательность важна).
Также можно используя .hint() намеренно указать определённый index который ты хочешь использовать для query.

pax 18.06.2013 17:03

Ответ: MongoDB
 
У меня условие было 1:1 твое)

pax 21.06.2013 12:04

Ответ: MongoDB
 
Еще одна задача: Хочется выводить игроку его примерное место среди всех игроков по какому-то параметру. Как бы это лучше провернуть? Из мыслей было сделать на каждый параметр запись в отдельную таблицу со всеми игроками сразу... т.е. получить сразу всю таблицу отсортированную в php, присвоить номера и записать в одну запись как массив. Потом делать по ней поиск. Но чет думаю может не правильно... Если игроков будет пару миллионов к примеру, то как такой скрипт отработает?

moka 21.06.2013 14:35

Ответ: MongoDB
 
Кешировать такие данные, будет в разы эфективнее, нежели запрашивать их каждый раз.
Чтобы получить их, тебе нужно посчитать число записей, у которых значение выше того что ты запрашиваешь. Например у тебя есть 5 записей, со значением фрагов: 2, 5, 7, 9, 15. Тебе нужно найти на каком месте находиться игрок с 9 фрагами:
PHP код:

db.players.find({ frags: { $gte} }).count() 

Получишь число, которое является позицией с верху относительно всех записей игроков в бд. Если нужен процент от топа, тут всё просто
PHP код:

(total position) / total 

Индекс по полю которому ищешь - очень улучшит ситуацию.
Но count это всё равно O(n) операция, следственно если ты запрашиваешь из 10к игроков кого-то с серидины, то бд нужно пролистать 5к игроков, чтобы их посчитать.. Даже с индексом, это всё равно относительно долго.

Следственно имей отдельную collection позиций, и там всё очень тупо:
_id, timestamp, frags
Где _id будет такой же как и _id в collection самих player, timestamp - когда запись была обновлена в последний раз и frags - будет уже высчитанная позиция.
И если запрашиваются данные о позиции, грузи их, если их нету или они устарели (я бы раз в день обновлял), то обнови, и выдай.
Если же тебе нужны эти данные не по запросу а всегда, то тебе нужен cron job, что будет это делать периодически.

jimon 21.06.2013 19:16

Ответ: MongoDB
 
таблица рейтинга это хеш мап с ключем = очки, а место там это индекс бокса в который value попадет
проще чтобы сервер это хранил отдельно от монги, не уверен чтобы именно индекс бокса можно у монги получить, хотя внутри думаю всё и так на хешмапах

moka 21.06.2013 20:56

Ответ: MongoDB
 
Внутри всё хешиться и весьма отлично. А вот про индекс, тут нет.
Получить позицию индекса нельзя, т.к. это не будет работать в случае с шардами баз данных, т.к. каждая из них будет иметь свой список хешей, и не будет знать о чужих списках, следственно посчитать позицию индекса не сможет. А большой упор в монго - это как раз шардинг.
Поэтому это лежит на плечах самих разработчиков.

Конечно можно иметь отдельный процесс, например мелкий node.js, в 50 строк. При запуске он будет загружать все данные и создавать все списки в памяти и их сортировать, затем периодически обновлять, и используя например ZeroMQ можно получать данные какие нужно от другого процесса, PHP или т.п.

Делать подобного рода процесс в бд, я бы не стал, т.к. это semi-realtime данные, и оперировать и обновлять их будет в разы эфективнее в памяти на не в бд.

goplanb 19.07.2013 21:09

Вложений: 3
нужен специалист по Mongobd помогите плиззб я делаю лабораторную работу, к информатике не имею ни какого отношения, что описано в этой функции

а что описывает это действие

и это

moka 19.07.2013 21:43

Ответ: MongoDB
 
Инфа по MapReduce тут: http://docs.mongodb.org/manual/core/map-reduce/
Вырванные методы из контекста - мало чего говорят.

goplanb 19.07.2013 22:31

Ответ: MongoDB
 
Цитата:

Сообщение от moka (Сообщение 263848)
Инфа по MapReduce тут: http://docs.mongodb.org/manual/core/map-reduce/
Вырванные методы из контекста - мало чего говорят.

Мне надо 2-3 преддожения на самом приметимном уровне

moka 19.07.2013 22:39

Ответ: MongoDB
 
Запрос листает все закупки от разных пользователей, и подсчитывает сколько покупок сделал каждый пользователь и сколько средняя арифметическая стоимость всех покупок по каждому пользователю.


Часовой пояс GMT +4, время: 06:29.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot