Как стать автором
Обновить

Комментарии 38

еще разок? для непонятливых? :)
простите, случайно в два одинаковых окна глянул
мм… как ты топики о разных вещах
Извините конечно, но вы реально офф документацию переписываете. Чтобы понять MongoDB достаточно просто знать, что все запросы — это вызов функций JavaScript, а перечень этих функций можно глянуть в доках.

С таким же успехом можно переписывать документацию к чему угодно.
Вы не задумывались о том, что если Вам это не нужно, то это не значит, что это не нужно другим?
Я не говорил, что материал не нужный. Скорее этот материал маловостребован, ибо когда хочешь освоится с новой базой ищешь описание драйвера для работы с ней, а не описания запросов shell'a.
Смотрю русскую документацию и вижу в основном ссылки на английскую версию. Может оформите как перевод?
Я не переводил что-то конкретное, я делал выборки для себя основных моментов
>Мы хотим получить последние 10 комментариев. На помощь нам приходит оператор $slice:
>> db.blog.posts.findOne( { }, { «comments»: { "$slice": 10 } } );

>Если нужно получить последние 10 комментариев пишем вот так:
>> db.blog.posts.findOne( { }, { «comments»: { "$slice": -10 } } );

Для разных вариантов параметров у Вас одинаковое пояснение.
спасибо, исправил
Хм… А примера, который есть в английской википедии, и который был для меня окончательно самой-смотри-как-круто-фичей в mongoDB нет.
Итак, напишу, ежели кому интересно:

Если запрос достаточно сложный, и базовых средств либо знаний не хватает, то всегда можно воспользоваться механизмом $where. То есть можно написать сложную логику получения данных, включая if-ы, и вернуть результат, чего в обычных базах данных добиться очень и очень сложно (имею в виду условия и циклы внутри SQL-запросов).
Синтаксис прост: в качестве параметра передаётся функция:
db.foo.find({$where : функция})

При этом используется объект (переменная) this, по сути — курсор, у которой можно получать свойства.
Функция должна вернуть true или false, что означает попадёт строка в выборку или нет.
Вот пример из википедии:
db.foo.find({$where : function() { return this.x == this.y; }})

При этом также можно использовать вложенные OR или AND, как в классических SQL — запросах:
db.foo.find({$where : function() { 
  if((this.cost>5 && this.cost<10 )|| (this.is_hidden != 1) || (this.link == this.url)){
    return true;
  }
  return false;
}})

Таким образом, курсор пробегает по базе, и выполняет проверки. разумеется, всё это можно ограничивать лимитами на количество строк, $where — всего лишь ключ в массиве параметров запроса.
Необходимо понимать, что это всё-таки медленне, чем обычные запросы, но всё равно достаточно быстро.
Дополнение, это Javascript, так что можно писать
<source lang=«javascript>
db.foo.find({$where: „this.cost > 1000“})

Такие записи ИМХО читаются проще.
Прощу прощения
 db.foo.find({$where: "this.cost > 1000"})
И последнее дополнение.
Упрощённый вариант:
db.foo.find({$where : function() { 
  return (this.cost>5 && this.cost<10 )|| (this.is_hidden != 1) || (this.link == this.url);
}})

Это только касаемо моего примера. Объяснять, думаю, не нужно.
Чем это отличается от выборки всех записей и фильтрации их на клиенте?
Во-первых, быстро. Допустим, запрашивается каталог на 10000 товаров или 40000000 твитов.
У нас постраничная навигация, поэтому один запрос 10-15 элементов, соотвествнно 10-15 условий.
Во-вторых, трафик.
В-третьих, никто в mysql никто не пытается запросить всё и фильтровать на клиенте.
Имею в виду, что 10-15 условий — это при достижении 10 элементов проверки прекращаются.
Почему это быстро, не пойму. Берутся, данные, извлекаются, далее с ними что-то делается: в первом случае это делается в процессе mongodb на javascript, во втором случае это делается на клиенте, который, возможно, делает это быстрее. Под клиентом я имею в виду программу, которая через драйвер работает с mongodb, возможно, на этом же компьюетере, так что трафик тут не в счёт.

> В-третьих, никто в mysql никто не пытается запросить всё и фильтровать на клиенте.
Так я и говорю, что то что вы описали, это похоже на «запросить всё и фильтровать на клиенте», просто фильтруется внутри mongodb процесса. Принципиальной разницы не вижу.

Естественно, что для обработки в клиенте не нужно запрашивать *все* записи, итерируемся по всем записями, пока не наберём нужное кол-во записей, далее процесс итерации обрываем.

Вот сделал простенький тест. У меня щас в монго базе 5.5 миллионов записей.
Вот код скрипта — ищется 10000 записей, удовлетворяющих условию: в URL должен быть фрагмент «10». В начале делается выборка с $where условием, далее выборка записей с проверкой в клиенте. Вторая выборка работает быстрее.
Скрипт: dumpz.org/115976/
Результаты (в секундах):
1) 1.94
2) 1.31

На поле url не наложен индекс, думаю, если б он там был, то вариант с логикой внутри mongo оказался бы быстрее.
>возможно, на этом же компьюетере

Вроде как это не рекомендуется из-за неограниченного аппетита Монго к оперативке.
Как понимать слова «вроде как»? Вы не уверены в том, что говорите?

Лично у меня всё работает. Ну да, монго выжрала все 16гб памяти, но ничего не падает, если кому-то нужна память, она выделяется за счёт той памяти, что заняла монго. Во всяком случае, так это выглядит по ощущениям. Свопинга нет. Размер файлов баз данных монги на диске — 260 гигабайт.
Помню, что читал об этом, в том числе и на хабре, но пруф нагуглить не смог. Не уверен в том, что уже занятая монгой память будет выделяться для других приложений и в любом случае это лишние задержки для других приложений.
«Вроде как», «читал», «нагуглить не смог», «не уверен», «в любом случае». Спасибо, я понял вашу точку зрения :)
Верно, еслиесть возможность, стоит использовать родные способы фильтрации. Но имхо просто упомянуть о возможности всё-таки стоило.
Стоит упомянуть, что $whare тормозит, на шардинге не работает и вообще рекомендуется для сложных запросов делать map/reduce.
НЛО прилетело и опубликовало эту надпись здесь
> Вот так можно найти всех пользователей с именем joe или Joe:
> db.users.find( { «name»: /joe/i } );

Нет, эта команда делает нечто другое. Она ищет записи, у которых в поле name встречается фрагмент «joe», так что «Joe Porn» и «ABCjoE» также будут найдены.
да, вы правы. Оно ищет вхождение подстроки. Исправлю
> db.users.find( { numbers: { $in: [ 390, 754, 454 ] } } );
> т.е. билет должен обязательно содержать эти три номера.

$in — numbers должен быть равен любому элементу из входного массива (т.е. присутствует в массиве)
$all — все элементы входного массива должны присутствовать в numbers
согласен, исправил
Итого: топик — пересказ официальной документации, в нём уже нашли 3 ошибки.

> Хоть и некоторые писали относительно моего предыдущего топика MongoDB: Создание, обновление и удаление документов, что это пересказ офф. документации, я с этим не полностью согласен.

С чем именно вы несогласны? Вы считаете, что это не пересказ документации?

> Мне показалось, что информация в нём оказалось кому-то полезной

Вы знаете, на хабре несколько десятков тысяч пользователей. Любая информация будет кому-то полезна, но это не повод тащить её всю сюда.

Ваш топик интересен, вероятно, тем, кто сейчас планирует начать работать с монго, и кто плохо знает английский язык. Ещё через 2-3 месяца выйден несколько новых версий, и ваш топик будет уже немного устаревшим. Поэтому даже для тех 84 человек, которые поместили его (уже текущий топик) в избранное, он по большей части окажется малополезным — имеет смысл читать либо сейчас, либо никогда.

Хотите сделать доброе дело? Возьмите да переведите документацию как документацию. Сделайте какую-то синхронизацию с оригиналом, чтобы можно было держать перевод up-to-date. Поднимите вики, найдите добровольцев, и вместе переводите. А на хабре устройте анонс, это будет хорошо и правильно.
увидел, что у монго уже есть русская документация, полупустая. может быть стоит переводить прямо в неё?
Вот лучше бы попробовали хоть что-то простое сделать с этой базой и расписали нюансы. Например, их там с индексами немерено. Например, MapReduce в один поток на сервере делается (кстати, $where, вроде, — тоже, но тут уже не помню).

А ваш топик — это очень краткая выжимка из официальной доки. Пользы ноль. Если же цель — заинтересовать, то это делается совершенно по-другому.
Поддерживаю. С индексами там все совсем не прозрачно. Недавно столкнулся с тем, что если поиск идет по range в multikey, то использоваться будет только одна из границ.

Т.е.

collection:
{«posts»:[{likes: 1}, {likes: 2}]},
{«posts»:[{likes: 3}, {likes: 4}]},
{«posts»:[{likes: 1}, {likes: 3}]}

И индекс на posts.likes, то при запросе:

db.collection.find( { «posts.likes»: {$gt:2, $lt:4} } );

Будет использоваться только условие $gt:2.

Это одно из нововведений 2.0 из-за которого придется что-то придумывать.
Там еще с geo-индексами куча приколов…
Может Я чего-то не уловил, но где проблемы?
>
> db.items1.find({price: {$gt: 0.4, $lt: 2.5}})
{ "_id": ObjectId(«4f3fc3fe0f53b1481211b202»), «name»: «eggs», «quantity»: 10, «price»: 1.5 }
{ "_id": ObjectId(«4f3fc40f0f53b1481211b204»), «name»: «tomatoes», «quantity»: 30, «price»: 0.5 }
>
> db.items1.find({price: {$lt: 2.5, $gt: 0.4}})
{ "_id": ObjectId(«4f3fc3fe0f53b1481211b202»), «name»: «eggs», «quantity»: 10, «price»: 1.5 }
{ "_id": ObjectId(«4f3fc40f0f53b1481211b204»), «name»: «tomatoes», «quantity»: 30, «price»: 0.5 }
>
> db.items1.find()
{ "_id": ObjectId(«4f3fc3fe0f53b1481211b202»), «name»: «eggs», «quantity»: 10, «price»: 1.5 }
{ "_id": ObjectId(«4f3fc40e0f53b1481211b203»), «name»: «bacon», «quantity»: 3, «price»: 3.5 }
{ "_id": ObjectId(«4f3fc40f0f53b1481211b204»), «name»: «tomatoes», «quantity»: 30, «price»: 0.5 }
{ "_id": ObjectId(«4f3fc4520f53b1481211b205»), «name»: «bacon222», «quantity»: 3, «price»: 4.5 }
> db.version()
2.0.2

Извиняюсь, dizer, уже увидел(

> db.items1.find({price: {$gt:0.6, $lt: 1.1}})
{ "_id": ObjectId(«4f3fcd8dfd19ed924f2b7184»), «name»: «b», «quantity»: 30, «price»: [ 0.5, 7.5 ] }
{ "_id": ObjectId(«4f3fcd91fd19ed924f2b7185»), «name»: «c», «quantity»: 30, «price»: [ 0.5, 7.5 ] }
{ "_id": ObjectId(«4f3fcd98fd19ed924f2b7186»), «name»: «d», «quantity»: 30, «price»: [ 0.5, 1.5 ] }

>Это одно из нововведений 2.0 из-за которого придется что-то придумывать.
Кстати как решаете и для чего это нужно?

Судя по полям posts and likes — каждому посту присваивается количество лайков пользователей, а find(), для поиска (нравится больше 10, но меньше 100 человекам)? У Меня вопрос — для чего?

ЗЫ:
Ну не в mysql же делаете SELECT… WHERE > AND <?
Это был просто пример. Пришлось по другому коллекцию строить.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории