﻿1
00:00:00,560 --> 00:00:05,040
Hello. I'll be introducing Voyage,
a wrapper for NoSQL databases,

2
00:00:05,560 --> 00:00:07,880
in this class.

3
00:00:08,120 --> 00:00:11,520
The goal is to let you build
a real application.

4
00:00:11,680 --> 00:00:15,680
You'll be able to store objects
like TinyBlog with Voyage,

5
00:00:16,080 --> 00:00:19,200
in a Mongo database,
and deploy on a real service.

6
00:00:19,400 --> 00:00:20,880
I also wanted to show you

7
00:00:21,200 --> 00:00:23,680
an easy way to store objects.

8
00:00:24,080 --> 00:00:27,120
Voyage is a simple solution.

9
00:00:28,640 --> 00:00:30,320
First, what is MongoDB?

10
00:00:30,760 --> 00:00:35,680
Mongo is a new document-oriented
NoSQL database.

11
00:00:36,840 --> 00:00:40,280
It features a powerful query language.

12
00:00:40,440 --> 00:00:44,440
Mongo is also one of the most popular
DBs, with CouchDB and Riak.

13
00:00:44,600 --> 00:00:48,240
We'll be using Mongo and Voyage.

14
00:00:48,480 --> 00:00:52,480
Actually, Voyage is a mapper.
It takes objects and maps them

15
00:00:53,360 --> 00:00:56,680
on MongoDB, almost automatically,
for the programmer.

16
00:00:56,840 --> 00:00:58,880
If you've done Java on Hibernate

17
00:00:59,040 --> 00:01:02,120
Voyage is the equivalent of Hibernate
for MongoDB.

18
00:01:02,400 --> 00:01:03,960
And it's made for Pharo.

19
00:01:05,120 --> 00:01:08,680
Here are Voyage's features.
It's very simple.

20
00:01:08,840 --> 00:01:12,320
It ensures object identity
when you reload them.

21
00:01:13,000 --> 00:01:15,320
It provides error-handling.

22
00:01:15,480 --> 00:01:18,840
And it also implements
a connection pool

23
00:01:19,000 --> 00:01:21,160
to speed things up.

24
00:01:22,720 --> 00:01:25,360
To start simple,
the first thing we'll do

25
00:01:25,520 --> 00:01:28,640
is create a MongoRepository.

26
00:01:28,800 --> 00:01:31,520
It uses these expressions:

27
00:01:32,240 --> 00:01:35,680
You want to access
your Mongo database,

28
00:01:35,840 --> 00:01:37,920
which is managed from outside Pharo.

29
00:01:38,320 --> 00:01:41,880
Often, when we are in prototype mode,

30
00:01:42,040 --> 00:01:44,440
we use a Mongo database
in the memory.

31
00:01:44,600 --> 00:01:47,600
It's referred to here
as Mongo Memory Repository.

32
00:01:48,040 --> 00:01:52,440
You don't need a Mongo database.
First, you prototype your application.

33
00:01:53,040 --> 00:01:58,080
When it is running right,
you switch the memory repository

34
00:01:58,360 --> 00:02:01,560
into a real repository,
and tackle your outside DB.

35
00:02:01,720 --> 00:02:04,000
That's the way to proceed.

36
00:02:07,400 --> 00:02:08,680
To illustrate Mongo,

37
00:02:09,040 --> 00:02:13,240
we have a simple model
of superheroes with superpowers,

38
00:02:13,680 --> 00:02:16,440
their armor and weapons.

39
00:02:16,880 --> 00:02:21,440
You'll be able to do the exercise
based on what I show you in the course.

40
00:02:21,600 --> 00:02:23,160
This is the support.

41
00:02:23,560 --> 00:02:26,680
I think you'll enjoy scripting Superman.

42
00:02:27,280 --> 00:02:32,240
First, let's look at how
Hero and Power operate.

43
00:02:33,400 --> 00:02:38,920
Basically, we have a Hero class,
with a name, level, and powers.

44
00:02:39,880 --> 00:02:43,720
I have an accessory for the name,
a setter for the name.

45
00:02:43,880 --> 00:02:45,640
Same for the level, here.

46
00:02:46,000 --> 00:02:48,040
And I manage the powers
as a set.

47
00:02:48,200 --> 00:02:53,000
If powers is empty,
I put in a set.

48
00:02:53,600 --> 00:02:56,400
When I can add a power,
I add one to the set.

49
00:02:56,560 --> 00:02:59,040
So it's really very basic.

50
00:03:00,720 --> 00:03:04,560
For the moment, the powers
only have a name.

51
00:03:05,720 --> 00:03:08,920
You can write the name or not.

52
00:03:10,000 --> 00:03:13,360
Now, the point is
to find a way to declare

53
00:03:13,800 --> 00:03:17,000
that my domain classes
are stored in a database.

54
00:03:17,240 --> 00:03:22,600
The root class idea gives us
an entry point for our database.

55
00:03:23,160 --> 00:03:27,720
It can be any class in the system,
and it is marked as the root

56
00:03:28,080 --> 00:03:32,280
with a class method (I emphasize class)
called isVoyageRoot.

57
00:03:33,800 --> 00:03:38,640
This is how we do it for Hero class:
isVoyageRoot returns true.

58
00:03:39,360 --> 00:03:43,400
At this point, Voyage knows
I will be able to store my heroes

59
00:03:43,800 --> 00:03:45,360
in the Mongo database.

60
00:03:46,640 --> 00:03:48,960
Let's do Spiderman.

61
00:03:49,240 --> 00:03:51,880
His name is Spiderman,
his level is epic.

62
00:03:52,240 --> 00:03:56,720
His powers are his super strength,
his ability to climb walls,

63
00:03:57,160 --> 00:04:01,760
and the spider instincts
he is purported to have.

64
00:04:02,440 --> 00:04:04,480
I save that information.

65
00:04:04,880 --> 00:04:09,400
"Save" tells Voyage
to take this superhero,

66
00:04:09,560 --> 00:04:11,160
and store it in the base.

67
00:04:11,400 --> 00:04:15,000
We do the same thing
with Wolverine and his powers,

68
00:04:15,160 --> 00:04:16,600
and save that data.

69
00:04:16,880 --> 00:04:18,880
Now, if I look at my Mongo base,

70
00:04:19,040 --> 00:04:21,440
using db.Hero.find,

71
00:04:21,800 --> 00:04:21,840
I see my hero Spiderman,

72
00:04:25,480 --> 00:04:27,280
and I should see his powers.

73
00:04:27,640 --> 00:04:29,960
This is where you have
to be careful.

74
00:04:30,360 --> 00:04:34,920
His superpowers are described
in full here.

75
00:04:35,360 --> 00:04:37,480
Same for Wolverine, etc.

76
00:04:39,880 --> 00:04:43,640
Once you've done that,
you can do lots with Pharo.

77
00:04:43,800 --> 00:04:48,080
I won't go into the details.
But I can select all the superheroes...

78
00:04:48,240 --> 00:04:51,320
That gives me Spiderman
and Wolverine.

79
00:04:51,640 --> 00:04:54,960
I can say find Spiderman...

80
00:04:55,240 --> 00:05:01,160
I can say I want to find all superheroes
who have an epic level.

81
00:05:02,080 --> 00:05:04,720
That gives me my two superheroes.

82
00:05:06,560 --> 00:05:09,280
I can also express it differently.

83
00:05:09,440 --> 00:05:12,720
Actually, the Mongo database

84
00:05:13,040 --> 00:05:16,160
understands Json,
so I can create Json on the fly,

85
00:05:16,440 --> 00:05:18,800
inject it, and do Json-based queries.

86
00:05:19,080 --> 00:05:21,600
Let's say I want to know

87
00:05:22,320 --> 00:05:24,560
which superhero is named Spiderman.

88
00:05:24,760 --> 00:05:29,760
But I've expressed it in Json form,
as dictionary, so it returns an entry.

89
00:05:30,880 --> 00:05:33,440
I can do the same thing
with "select Many."

90
00:05:33,680 --> 00:05:38,000
It depends on the easiest way
for expressing your query.

91
00:05:38,160 --> 00:05:40,640
But that's a detail for you, right now.

92
00:05:40,960 --> 00:05:43,400
You can do much more advanced queries.

93
00:05:43,680 --> 00:05:46,280
I can say "select all" the heroes

94
00:05:46,920 --> 00:05:51,280
or "many" of the superheroes
with an epic level.

95
00:05:51,440 --> 00:05:54,480
I can sort their names
in ascending order.

96
00:05:54,640 --> 00:05:58,400
I set a limit of 10,
and say I want to start at page 0.

97
00:05:58,560 --> 00:06:01,880
That will bring me sections
of the database.

98
00:06:03,120 --> 00:06:05,760
When you need that,
look in the documentation.

99
00:06:06,360 --> 00:06:10,280
We can do other operations,
like count our superheroes.

100
00:06:10,680 --> 00:06:14,160
I can count those whose possess
a certain property.

101
00:06:14,440 --> 00:06:18,240
I can remove some.
If I remove all, I empty the database.

102
00:06:18,560 --> 00:06:20,360
Be careful of that command.

103
00:06:20,520 --> 00:06:23,680
Here, I can select one,
and remove it.

104
00:06:24,520 --> 00:06:26,960
That hero will be removed from the base.

105
00:06:28,360 --> 00:06:31,000
These are all operations
that make sense.

106
00:06:31,880 --> 00:06:35,600
Now, the question that will arise
when using MongoDB

107
00:06:35,760 --> 00:06:39,840
is, what is the base root,
in Mongo lingo?

108
00:06:40,280 --> 00:06:42,760
When is a class defined as a root?

109
00:06:43,080 --> 00:06:46,640
The answer is,
if you want to query that class.

110
00:06:46,800 --> 00:06:48,200
That's the first rule.

111
00:06:48,320 --> 00:06:51,440
I define that class as a root,

112
00:06:51,600 --> 00:06:55,600
because I want to have access
to all the objects in the class.

113
00:06:55,880 --> 00:06:58,880
The other reason
is wanting to be able to share

114
00:06:59,200 --> 00:07:02,800
these objects between roots.

115
00:07:03,640 --> 00:07:06,800
Say I want to share powers,
to make it clearer.

116
00:07:07,240 --> 00:07:10,440
I want to be able to share powers
between heroes.

117
00:07:11,000 --> 00:07:15,160
In that case, I have to define
power as a root.

118
00:07:15,560 --> 00:07:16,760
Watch this.

119
00:07:17,560 --> 00:07:21,560
In our example, hero is a root.

120
00:07:21,720 --> 00:07:24,240
But power can also be a root.

121
00:07:24,520 --> 00:07:28,520
In Voyage, you can declare
any class as a root.

122
00:07:29,120 --> 00:07:31,160
Here is how to do it.

123
00:07:32,280 --> 00:07:37,040
I say Power class isVoyageRoot.

124
00:07:37,880 --> 00:07:42,040
Now, if I create the power "Fly,"

125
00:07:42,400 --> 00:07:44,960
and save it, it is in the base.

126
00:07:45,920 --> 00:07:47,840
Superstrength? The same.

127
00:07:48,000 --> 00:07:52,280
Now I'll be able to make a query

128
00:07:52,680 --> 00:07:55,520
that tells Voyage to get
the power to fly.

129
00:07:55,760 --> 00:08:00,160
I also want Voyage to get
the power of superhuman strength.

130
00:08:00,920 --> 00:08:03,240
And now I recreate Superman.

131
00:08:03,640 --> 00:08:05,080
I say, "Hey!

132
00:08:06,840 --> 00:08:11,120
I got these two powers, so there's
only one in the system, and I save it.

133
00:08:11,400 --> 00:08:15,280
But it's important for me
to reset the base

134
00:08:15,480 --> 00:08:18,720
so that it works right,

135
00:08:18,880 --> 00:08:22,240
whenever you change the basic schema.

136
00:08:23,600 --> 00:08:26,880
But now I want to show you
what I have now.

137
00:08:27,320 --> 00:08:30,520
Superman's powers
are described differently.

138
00:08:31,360 --> 00:08:35,640
The power isn't composed inside.
I have a reference to a power.

139
00:08:36,640 --> 00:08:41,440
That means if I have another superhero
who knows how to fly,

140
00:08:42,160 --> 00:08:46,640
I can share that superpower,
instead of having two instances.

141
00:08:47,440 --> 00:08:51,920
So, depending on your domain
and how you want to modelize it,

142
00:08:52,280 --> 00:08:54,320
you'll define roots differently.

143
00:08:54,480 --> 00:08:57,440
This silly example
is just to give you an idea.

144
00:08:57,720 --> 00:09:01,240
Actually, if I repeat myself,
you define a domain root

145
00:09:01,600 --> 00:09:07,040
if you want to query it
or share objects in the root.

146
00:09:09,560 --> 00:09:13,880
In Voyage, relationships are expressed

147
00:09:14,320 --> 00:09:17,360
the way "foreign keys" are
in relational databases.

148
00:09:17,640 --> 00:09:21,640
Voyage automatically handles
cyclic references of root objects.

149
00:09:21,840 --> 00:09:26,440
But be careful:
Voyage does not support cyclic references

150
00:09:26,880 --> 00:09:29,600
between embedded objects.

151
00:09:31,240 --> 00:09:35,800
You'll experiment, and see.
If you have roots, you're home safe.

152
00:09:36,320 --> 00:09:40,600
In this course, I wanted to show you
how easy it is to store objects

153
00:09:41,040 --> 00:09:43,160
in a Mongo database.

154
00:09:43,680 --> 00:09:48,120
If you want to know more, look at
Enterprise Pharo: a Web Perspective.

155
00:09:48,280 --> 00:09:50,200
It's in the MOOC resources.

156
00:09:50,600 --> 00:09:55,680
You can also refer to a little tutorial
on building the superhero base.

157
00:09:56,840 --> 00:09:58,200
You can learn it all.