Java development 2.0: Вторая волна разработки Java-приложений. MongoDB – хранилище данных NoSQL со всеми (полезными) признаками СУРБД

Создание документов и выполнение запросов с помощью Java-кода и Groovy

Если вы изучаете хранилища данных типа NoSQL, не забудьте включить в ваш список MongoDB, хранилище, которое часто называют NoSQL-СУРБД. Познакомьтесь с пользовательским API MongoDB - интерактивной shell-оболочкой, изучите возможности выполнения динамических запросов в стиле СУРБД и функций MapReduce, используемых для ускорения и упрощения вычислений. Затем мы предлагаем вам перейти непосредственно к созданию, поиску и другим операциям с данными с помощью встроенного в MongoDB драйвера языка Java™ и удобного приложения-обертки от Groovy под названием Gmongo.

Эндрю Гловер, президент компании, Stelligent Incorporated

Эндрю ГловерЭндрю Гловер является президентом компании Stelligent Incorporated , которая помогает другим фирмам решать проблемы качества программного обеспечения. Для этого используются эффективные стратегии тестирования и технологии непрерывной интеграции, которые позволяют коллективам разработчиков постоянно контролировать качество кода, начиная с ранних стадий разработки. Просмотрите блог Энди , там можно найти список его публикаций.



27.02.2012

Развить навыки по этой теме

Этот материал — часть knowledge path для развития ваших навыков. Смотри Использование NoSQL для анализа данных большого объема

Кардинальное отличие документо-ориентированных баз данных, таких как MongoDB и CouchDB, от реляционных баз данных состоит в том, что вместо привычных таблиц данных документо-ориентированные базы хранят информацию в форме документов. С точки зрения разработчика ПО документо-ориентированные данные (данные без жесткой схемы) являются более простыми и значительно более гибкими в управлении, нежели реляционные данные. В отличие от реляционных данных, хранящихся в жестко фиксированной структуре таблиц, строк и столбцов, связанных определенными взаимоотношениями, документы создаются индивидуально и могут хранить любую необходимую информацию.

О MongoDB из первых рук

Узнайте больше об этой документо-ориентированной базе данных с открытым кодом от Элиота Хоровитца, технического директора компании 10gen, из предлагаемого технического подкаста. Прослушать.

Среди всех документо-ориентированных баз с открытым кодом MongoDB часто упоминается как база данных NoSQL со свойствами СУРБД. Одним из таких свойств является поддержка MongoDB динамических запросов, не требующих предварительно заданных функций MapReduce. Кроме того, MongoDB поставляется с интерактивной командной оболочкой, что значительно облегчает доступ к данным. Встроенная поддержка шардинга обеспечивает высокий уровень горизонтального масштабирования между несколькими узлами.

API MongoDB представляет собой органичное сочетание объектов JSON и функций JavaScript. Разработчики могут работать непосредственно с базой данных MongoDB либо с помощью командной оболочки, либо с помощью драйвера соответствующего языка, который обеспечивает доступ к объектам базы данных. Этот драйвер не является JDBC-драйвером, так что вам не придется иметь дело с ResultSet или PreparedStatements.

Еще одним преимуществом MongoDB является высокая скорость обработки данных, которая объясняется выбранным подходом к записи информации в базу: данные хранятся в памяти и записываются на диск не сразу, а в фоновом потоке.

Об этой серии

Специфика современных разработок на языке Java коренным образом отличается от методов, характерных для начального этапа развития Java-технологий. Использование развитых открытых инфраструктур и предоставляемых в аренду надежных сред развертывания позволяет быстро и с минимальными затратами собирать, тестировать, запускать и поддерживать Java-приложения. В предлагаемой серии статейЭндрю Гловер рассматривает ряд технологий и инструментов, лежащих в основе новой парадигмы Java-разработки.

В этой статье вам предстоит поближе познакомиться с MongoDB. Я воспользуюсь тем же подходом, что и при изучении CouchDB (см. Ресурсы), когда мы на примере обработки штрафных квитанций за неправильную парковку убедились в высокой гибкости хранилищ данных без жесткой схемы. Поскольку двумя наиболее существенными особенностями MongoDB являются ее API и поддержка динамических запросов, мы сфокусируемся именно на этих свойствах и рассмотрим примеры, демонстрирующие на практике командную оболочку MongoDB и драйвер языка Java. Затем я познакомлю вас с Gmongo - приложением Groovy, которое поможет нам справиться с «многословностью» MapReduce и изучить основы реализации MapReduce в MongoDB. Собственно, реализация функций MapReduce в MongoDB является еще одной отличительной чертой этой NoSQL-базы данных.

Когда не нужна жесткая схема данных?

Базы без жестко определенной схемы данных подходят далеко не для каждой области применения; именно поэтому имеет смысл разобраться, в каких случаях документо-ориентированная база данных имеет преимущества по сравнению с реляционной базой данных. Гибкая структура документов важна для областей применения, в которых данные могут храниться в произвольном формате, сохраняя при этом соответствие единой базовой модели. Классическим примером таких данных являются визитные карточки. Возьмите стопку таких карточек, и вы убедитесь, что данные на них представлены в самых разных форматах: на некоторых карточках указан номер факса или URL компании, на других - адрес электронной почты, на третьих - два телефонных номера или даже ссылка на Твиттер. Данные могут быть разными, но модель, или, точнее, функциональное предназначение, остаются неизменными, - визитная карточка содержит контактную информацию.

Безусловно, модель визитной карточки можно создать и в реляционной базе данных, однако процесс разработки модели в этом случае рискует оказаться достаточно сложным. В реляционной модели у вас будет множество записей с пустыми значениями в столбце, соответствующем номеру факса (например), и только одна или две записи, где это поле будет непустым. Кроме того, вам потребуется указать типы данных в столбцах, а это задача может быть непросто. Так, например, как определить длину строки, содержащей адрес? Я уверен, что вы никогда не задумывались о необходимости сохранить в базе адрес человека, проживающего в населенном пункте под названием Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch, не правда ли? Тем не менее такой населенный пункт существует.

Задача моделирования визитной карточки в документо-ориентированной базе данных решается гораздо проще. Поскольку в этом случае вы не связаны жесткой структурой данных, ваш документ может содержать любые данные произвольной длины. Учитывая природу данных, указываемых обычно на визитках, безусловно, есть смысл использовать в качестве модели документ с набором различных свойств.

Большинство хранилищ данных без жестко заданной структуры не поддерживают полностью принципы ACID (Atomicity, Consistency, Isolation и Durability – атомарность, согласованность, изоляция и долговечность), что является серьезным препятствием для использования подобных хранилищ в тех случаях, когда надежность и согласованность играют ключевую роль. Сторонники NoSQL-подхода утверждают в свою защиту, что эти принципы работают до тех пор, пока не появляются проблемы со сбоями, которые становятся просто неизбежны при масштабировании с использованием множества узлов. Отсюда следует, что хранилища без жесткой структуры данных обладают большими возможностями масштабирования по сравнению с реляционными системами, а это, в свою очередь, означает, что документо-ориентированные хранилища представляют собой удачный выбор для веб-приложений.


Начинаем работу с MongoDB

Начать работу с MongoDB очень просто, особенно учитывая тот факт, что разработчики этого хранилища предлагают загрузочные файлы для каждой конкретной операционной системы. Если вам нужно установить MongoDB на Mac OS X, вы просто загружаете соответствующий бинарный файл, раскрываете архив, указываете директорию, в которой MongoDB будет хранить содержимое вашей базы данных, и создаете саму базу данных с помощью команды mongodb (не забудьте указать соответствующему процессу место, где следует хранить базу).

Листинг 1 демонстрирует пример запуска MongoDB с указанием директории data/db в качестве места хранения данных. Обратите внимание, что я использую в команде флаг детализации вывода. Чем больше параметров v, тем больше детальной информации будет включено в вывод команды.

Листинг 1. MongoDB для Mac OS X
iterm$ ./bin/mongod — dbpath ./data/db/ ——vvvvvvvv

После запуска MongoDB в вашем распоряжении оказывается интерактивная командная оболочка, которая активизируется командой mongo. Результат выполнения этой команды показан в листинге 2.

Листинг 2. Запуск командной оболочки MongoDB
iterm$ ./bin/mongo
MongoDB shell version: 1.6.0
connecting to: test
>

Обратите внимание: запуск командной оболочки автоматически подключает вас к хранилищу test. Я воспользуюсь этим хранилищем для создания и поиска документов с помощью JavaScript и JSON.


Создание и поиск документов

Точно так же как и в CouchDB, для создания документов в MongoDB используется JSON (сами документы хранятся как объекты BSON - бинарной формы JSON, выбранной за высокую эффективность). Для создания штрафной квитанции средствами командной оболочки MongoDB вам нужно создать документ JSON, аналогичный документу, приведенному в листинге 3:

Листинг 3. Простой документ JSON
> ticket =  { officer: "Kristen Ree" , location: "Walmart parking lot", vehicle_plate: 
  "Virginia 5566",  offense: "Parked in no parking zone", date: "2010/08/15"}

В ответ на ввод указанных выше данных MongoDB выведет отформатированный документ JSON (см. листинг 4):

Листинг 4. Данные, возвращаемые MongoDB
{
  "officer" : "Kristen Ree",
  "location" : "Walmart parking lot",
  "vehicle_plate" : "Virginia 5566",
  "offense" : "Parked in no parking zone",
  "date" : "2010/08/15"
}

Я только что создал JSON-представление штрафной квитанции и присвоил ей имя ticket. Для сохранения этого документа в базе данных я должен связать его с коллекцией, которая является аналогом схемы данных в реляционном хранилище. Команда, приведенная в листинге 5, связывает ticket с соответствующей коллекцией:

Листинг 5. Сохранение экземпляра ticket
> db.tickets.save(ticket)

Обратите внимание на то, что MongoDB не требует предварительного создания коллекции. Коллекция создается автоматически при первом ее упоминании.

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

Поиск документов

Чтобы получить все документы коллекции, достаточно просто вызвать команду, показанную в листинге 6:

Листинг 6. Поиск всех документов коллекции
> db.tickets.find()
{ "_id" : ObjectId("4c7aca17dfb1ab5b3c1bdee8"), "officer" : "Kristen Ree", "location" : 
  "Walmart parking lot", "vehicle_plate" : "Virginia 5566", "offense" : 
  "Parked in no parking zone", "date" : "2010/08/15" }
{ "_id" : ObjectId("4c7aca1ddfb1ab5b3c1bdee9"), "officer" : "Kristen Ree", "location" : 
  "199 Baldwin Dr", "vehicle_plate" : "Maryland 7777", "offense" : 
  "Parked in no parking zone", "date" : "2010/08/29" }

Команда find без параметров возвращает список всех документов указанной коллекции (в нашем случае это коллекция с именем tickets).

Как видно из листинга 6, для каждого документа MongoDB создает свой идентификатор, значение которого хранится в поле _id.

Вы можете искать документы JSON по значению определенного поля. Так, например, для поиска всех штрафных квитанций, выписанных на парковке Walmart, я могу воспользоваться командой, показанной в листинге 7:

Листинг 7. Поиск по запросу
> db.tickets.find({location:"Walmart parking lot"})

Для поиска записей вы можете использовать значения любого поля, определенного в JSON-документе (в нашем примере это могут быть поля offense, _id, date и другие). Еще одна возможность поиска, которая продемонстрирована в листинге 8, - это поиск по значению поля (например, location), заданному с использованием регулярных выражений, который работает примерно так же, как выражение LIKE в SQL:

Листинг 8. Поиск с использованием регулярных выражений
> db.tickets.find({location:/walmart/i})

Параметр i в конце регулярного выражения (в нашем примере это просто слово walmart) указывает на то, что поиск должен вестись без учета прописных или заглавных букв.


Java-драйвер MongoDB

Java-драйвер MongoDB позволит вам абстрагироваться от большей части кода JSON и JavaScript, которые мы использовали в предыдущих разделах, так что вы будете работать непосредственно с Java API. Для использования Java-драйвера MongoDB загрузите его и добавьте соответствующий .jar файл в путь classpath (см. раздел Ресурсы).

Теперь представьте, что вам нужно добавить еще один объект ticket в коллекцию tickets, которая хранится в базе данных test. Чтобы сделать это с помощью драйвера Java, вы сначала подключаетесь к MongoDB, затем задаете базу данных test и коллекцию tickets (см. листинг 9):

Листинг 9. Использование Java-драйвера MongoDB
Mongo m = new Mongo();
DB db = m.getDB("test");
DBCollection coll = db.getCollection("tickets");

Для того чтобы создать JSON документ с помощью Java-драйвера, достаточно просто создать BasicObject и указать имена и значения, ассоциированные с этим объектом (см. листинг 10):

Листинг 10. Создание документа с помощью драйвера Java
BasicDBObject doc = new BasicDBObject();

doc.put("officer", "Andrew Smith");
doc.put("location", "Target Shopping Center parking lot");
doc.put("vehicle_plate", "Virginia 2345");
doc.put("offense", "Double parked");
doc.put("date", "2010/08/13");

coll.insert(doc);

Листинг 11 демонстрирует, насколько легко осуществить поиск документов и вывод результатов этого поиска с использованием драйвера Java:

Листинг11. Поиск документов с помощью драйвера Java
DBCursor cur = coll.find();
while (cur.hasNext()) {
 System.out.println(cur.next());
}

Для работы с MongoDB Java-разработчикам предлагается несколько библиотек, включая изящную абстракцию Groovy, созданную на основе встроенного драйвера Java. В следующем разделе мы рассмотрим приложение, которое позволит нам на практике познакомиться с некоторыми возможностями встроенного Java-драйвера и детальнее изучить приложение Groovy. Кроме того, наше приложение продемонстрирует функциональность MapReduce, которая используется в MongoDB для обработки коллекции документов.


Анализ блога в Твиттере средствами MongoDB

Сама по себе информация, хранящаяся в базе данных, не представляет особого интереса до тех пор, пока мы не начнем ее использовать. Рассмотрим приложение, с помощью которого мы сможем извлечь данные из Твиттера и сохранить их в MongoDB. Затем на основе полученных данных, мы вычислим два показателя: кто чаще всего ретранслирует мои сообщения в Твиттере и какое из моих сообщений получило больше всего ретвитов.

Для успешной работы приложения нам необходим интерфейс, обеспечивающий доступ к Твиттеру и получение данных. Для реализации этого интерфейса я воспользуюсь замечательной библиотекой Twitter4J, которая абстрагирует более или менее соответствующий принципам RESTful API-интерфейс Твиттера в виде обычного Java API (см. раздел Ресурсы). Я воспользуюсь этим интерфейсом для поиска посетителей моего блога. Полученные данные я преобразую в документ JSON наподобие того, что показан в листинге 12:

Листинг 12. Данные о посетителях микроблога в Твиттере в формате JSON
{ 
  "user_name" : "twitter user",
  "tweet" : "Podcast ...", 
  "tweet_id" :  9090...., 
  "date" : "08/12/2010" 
}

Листинг 13 демонстрирует фрагмент кода моего Java-приложения, где я использую встроенный Java-драйвер MongoDB и библиотеку Twitter4J, чтобы получить данные и сохранить их в MongoDB:

Листинг 13. Сохранение данных Твиттера в базе MongoDB
Mongo m = new Mongo();
DB db = m.getDB("twitter_stats");
DBCollection coll = db.getCollection("retweets");

Twitter twitter = new TwitterFactory().getInstance("<some user name>", "<some password>");
List<Status> statuses = twitter.getRetweetsOfMe();
for (Status status : statuses) { 
  ResponseList<User> users = twitter.getRetweetedBy(status.getId());
  
  for (User user : users) {
    BasicDBObject doc = new BasicDBObject();
    doc.put("user_name", user.getScreenName());
    doc.put("tweet", status.getText());
    doc.put("tweet_id", status.getId());
    doc.put("date", status.getCreatedAt());
    coll.insert(doc);
 }
}

Обратите внимание: база данных twitter_stats, используемая в листинге 13, создается по запросу; во время обращения к драйверу такой базы данных еще не существует. То же самое относится и к коллекции retweets. После создания базы данных и коллекции документов я средствами библиотеки Twitter4J получаю объект Twitter, с помощью которого извлекаю список 20 последних посетителей моего блога.

Twitter4J возвращает набор объектов Status, который представляет собой список посетителей моего микроблога. Для каждого элемента этого списка выполняется запрос на получение связанных с ним данных и создается новый элемент BasicDBObject, предназначенный для хранения этих данных в MongoDB. Далее сформированный документ сохраняется в базе данных.


MongoDB's MapReduce

Как только мы извлекли всю необходимую информацию из Твиттера и сохранили ее в базе данных MongoDB, мы можем перейти к операциям выборки и суммирования данных. Для того чтобы вычислить нужные показатели, мне потребуется выполнить несколько групповых операций. Сначала я определю суммарное количество записей для каждого посетителя Твиттера, а затем для каждого сообщения просуммирую записи, где это сообщение упоминается (или его идентификатор tweet_id).

Для групповых операций с данными MongoDB использует MapReduce. В самом общем виде подход, используемый алгоритмом MapReduce, можно описать следующим образом. Обработка группы данных выполняется в два этапа. Сначала на вход функции Map подается большой объем данных, которые эта функция разбивает на меньшие части и передает другим процессам для выполнения тех или иных действий. Затем функция Reduce собирает результаты обработки групп данных, определенных функцией Map, в единый вывод.

Поскольку базовым API MongoDB является JavaScript, функции MapReduce должны быть написаны на этом языке. Таким образом, несмотря на использование Java-драйвера, мне все равно пришлось бы использовать JavaScript для создания функций MapReduce, даже если я определю код JavaScript как String или объект, аналогичный BasicDBObject. Однако я попробую упростить себе жизнь и избавиться от излишнего кодирования. Вместо этого воспользуемся библиотекой-оберткой Java-драйвера MongoDB. Эта обертка называется Gmongo и предназначена для работы с Groovy. Мне все равно придется писать функции MapReduce на JavaScript, но благодаря многострочности строковых переменных Groovy это задача значительно упростится, главным образом потому, что мне не придется оформлять строковые переменные escape-символами.

Функции MapReduce на JavaScript

Чтобы определить, кто из пользователей Твиттера чаще всего ретранслирует мои записи, мне нужно выполнить две операции: сначала надо написать map-функцию для группировки документов JSON по полю user_name. Сделать это довольно просто – готовая функция приведена в листинге 14:

Листинг 14. Простая Map-функция на JavaScript
function map() {
  emit(this.user_name, 1); 
}

Моя map-функция предельно проста: для каждого переданного ей документа она возвращает свойство user_name этого документа. Функция использует вызов emit, вторым параметром которого является значение. Это значение в общем случае является счетчиком ключа, который для каждого документа равен 1. Вы поймете, как используется значение счетчика, когда мы перейдем к суммированию записей.

Итак, в листинге 14 я вызываю функцию emit, которой передаю ключ (свойство user_name) и значение. Переменная this в контексте моей map-функции представляет собственно документ JSON.

Теперь мне нужно определить функцию reduce (она показана в листинге 15), которая будет получать сгруппированные документы и суммировать соответствующие значения:

Листинг 15. Функция Reduce на JavaScript
function reduce(key, vals) {
  var sum = 0;
  for(var i in vals) sum += vals[i];
  return sum;
}

Как показано в листинге 15, при передаче в функцию reduce конкретных значений для параметров key и vals мы получим что-то вроде reduce("asmith", [1,1,1,1]) – в предположении, что в четырех разных документах параметр user_name был равен asmith, т.е. A. Smith ретранслировал мои сообщения 4 раза.

Выполнив цикл по всем значениям vals, функция reduce возвращает их сумму.

Функции MapReduce в Groovy

Теперь мне нужен Groovy-скрипт, который с помощью Gmongo интегрирует мои функции map и reduce (см. листинг 16):

Листинг 16 Скрипт Groovy для MapReduce
  mongo = new GMongo()
def db = mongo.getDB("twitter_stats")

def res = db.retweets.mapReduce(
    """
    function map() {
        emit(this.user_name, 1); 
    }
    """,
    """
    function reduce(key, vals) {
        var sum = 0;
        for(var i in vals) sum += vals[i];
        return sum;
    }
    """,
    "result",
    [:] 
)

def cursor = db.result.find().sort(new BasicDBObject("value":-1))
       
cursor.each{
  println "${it._id} has retweeted you ${it.value as int} times"
}

Как показано в листинге 16, сначала я создаю экземпляр Gmongo и подключаюсь к базе данных twitter_stats— аналогичные шаги мне пришлось бы выполнить и при использовании встроенного драйвера Java.

Затем я вызываю метод mapReduce для коллекции retweets. Драйвер Gmongo позволяет мне использовать ссылку на коллекцию вместо непосредственного извлечения этой коллекции, как мне пришлось сделать в листинге 13. Метод mapReduce использует 4 параметра: первые два являются строковыми представлениями функций map и reduce, написанными на JavaScript. Третий параметр – имя объекта, в котором хранится результат работы MapReduce. Последний параметр – произвольный запрос, необходимый для правильной обработки данных. Используя такой запрос, я могу передать функции MapReduce набор определенных документов JSON (например, документы, созданные в заданный период времени) или часть этого набора.

Далее я запрашиваю результирующий объект (который тоже является документом JSON) и вызываю sort. Вызов sort, приведенный в листинге 16, требует привести документ JSON к виду {value:-1} - это значит, что сортировка должна вестись по убыванию, чтобы максимальные значения оказались в начале списка. Возвращаемый объект cursor является циклическим итератором, так что я могу применить Groovy each непосредственно к этому объекту и вывести готовый отчет. Мой вывод представляет собой отсортированный по убыванию список пользователей Твиттера, наиболее часто ретранслирующих мои записи.

В результате выполнения скрипта, приведенного в листинге 16, должен появиться следующий вывод (см. листинг 17):

Листинг 17. Вывод MapReduce
bglover has retweeted you 3 times
bobama has retweeted you 3 times
sjobs has retweeted you 2 times
...

Теперь я знаю, кто чаще всего ретранслирует записи моего микроблога, но как насчет того, какая из моих записей получает наибольшее количество ретвитов? Для получения этой информации нам потребуется выполнить аналогичные действия: сначала я определю функцию map, которая группирует документы по свойству tweet вместо свойства user_name (см. листинг 18):

Листинг 18. Еще одна функция Map
function map() {
  emit(this.tweet, 1); 
}

В качестве бонуса нам не придется писать новую функцию reduce - мы можем использовать уже написанную нами функцию, поскольку она просто суммирует количество сгруппированных по ключу записей!


Заключение

Эта статья является весьма кратким и поверхностным обзором MongoDB и дает лишь самое общее представление о возможностях этого хранилища данных. Тем не менее я надеюсь, что даже такой краткий обзор помог вам понять, как отказ MongoDB от использования жесткой схемы данных обусловливает высокую гибкость этого хранилища. Это качество особенно важно для областей применения, в которых параметры разных элементов данных могут отличаться друг от друга, но сами эти элементы соответствуют одной и той же модели – как в рассмотренном нами примере с визитными карточками.

Несмотря на то, что MongoDB и CouchDB благодаря отказу от жесткой схемы данных обладают высокой гибкостью, эти хранилища отличаются друг от друга по остальным параметрам. Функции и механизмы управления данными в MongoDB аналогичны функциям реляционных хранилищ, поэтому разработчикам, привыкшим к СУРБД, проще работать с MongoDB. MongoDB поддерживает динамические запросы и «встроенные» языки программирования, такие как Java, Ruby или PHP, и при этом вы можете использовать функциональность MapReduce.

Документо-ориентированные хранилища применимы не для всех применений. Для приложений, работающих с финансовой информацией и характеризующихся большим количеством транзакций, лучше всего подходят традиционные ACID-СУРБД. Однако если вы разрабатываете приложение, требующее высокой пропускной способности и гибкой модели данных, MongoDB заслуживает вашего пристального внимания.

Ресурсы

Научиться

Получить продукты и технологии

  • Загрузить MongoDB и Java-драйвер вы можете на сайте MongoDB.org.
  • В качестве альтернативы встроенному драйверу Java Groovy предлагает свое решение, GMongo, загрузить которое можно Download GMongo здесь.

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Технология Java
ArticleID=795906
ArticleTitle=Java development 2.0: Вторая волна разработки Java-приложений. MongoDB – хранилище данных NoSQL со всеми (полезными) признаками СУРБД
publish-date=02272012