Skip to content

Commit b89b8de

Browse files
committed
DOCS-673 migrate server side code execution page
1 parent 87c25fa commit b89b8de

File tree

6 files changed

+443
-62
lines changed

6 files changed

+443
-62
lines changed

source/applications.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ The following documents outline basic application development topics:
3333
applications/drivers
3434
applications/optimization
3535
applications/database-references
36+
applications/server-side-code-execution
3637
applications/gridfs
3738
core/object-id
3839
core/capped-collections
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
==========================
2+
Server-side Code Execution
3+
==========================
4+
5+
.. default-domain:: mongodb
6+
7+
MongoDB supports server-side execution of JavaScript code using various
8+
methods.
9+
10+
.. note:: The JavaScript code execution takes a JavaScript lock.
11+
12+
.. _server-side-map-reduce:
13+
14+
Map-Reduce
15+
----------
16+
17+
MongoDB performs the execution of JavaScript functions for
18+
:doc:`/applications/map-reduce` operations on the server. Within these
19+
JavaScript functions, you must not access the database for any reason,
20+
including to perform reads.
21+
22+
See the :method:`db.collection.mapReduce()` and the
23+
:doc:`/applications/map-reduce` documentation for more information,
24+
including examples of map-reduce. See :ref:`map-reduce concurrency
25+
<map-reduce-concurrency>` section for concurrency information for
26+
map-reduce.
27+
28+
.. _server-side-eval:
29+
30+
``eval`` Command
31+
----------------
32+
33+
The :dbcommand:`eval` command, and the corresponding :program:`mongo`
34+
shell method :method:`db.eval()`, evaluates JavaScript functions on the
35+
database server. This command may be useful if you need to touch a lot
36+
of data lightly since the network transfer of the data could become a
37+
bottleneck if performing these operations on the client-side.
38+
39+
.. warning::
40+
41+
By default, :dbcommand:`eval` command requires a write lock. As such
42+
:dbcommand:`eval` will block all other read and write operations
43+
while it runs.
44+
45+
See :dbcommand:`eval` command and :method:`db.eval()` documentation for
46+
more information, including examples.
47+
48+
Running .js files via a mongo shell instance on the server
49+
----------------------------------------------------------
50+
51+
Running a JavaScript (.js) file using a :program:`mongo` shell instance
52+
on the server is a good technique for performing batch administrative
53+
work. When you run :program:`mongo` shell on the server, connecting via
54+
the localhost interface, the connection is fast with low latency.
55+
Additionally, this technique has the advantage over the
56+
:dbcommand:`eval` command since the command :dbcommand:`eval` blocks
57+
all other operations.
58+
59+
.. _server-side-where:
60+
61+
$where Operator
62+
---------------
63+
64+
To perform :doc:`/core/read-operations`, in addition to the standard
65+
operators (e.g. :operator:`$gt`, :operator:`$lt`), with the
66+
:operator:`$where` operator, you can also express the query condition
67+
either as a string or a full JavaScript function that specifies a
68+
SQL-like ``WHERE`` clause. However, use the standard operators whenever
69+
possible since :operator:`$where` operations have significantly slower
70+
performance.
71+
72+
.. warning::
73+
74+
Do not write to the database within the :operator:`$where`
75+
JavaScript function.
76+
77+
See :operator:`$where` documentation for more information, including
78+
examples.
79+
80+
Storing Functions Server-side
81+
-----------------------------
82+
83+
.. note::
84+
85+
We do **not** recommend using server-side stored functions if
86+
possible.
87+
88+
There is a special system collection named ``system.js`` that can store
89+
JavaScript functions for reuse.
90+
91+
To store a function, you can use the :method:`db.collection.save()`, as
92+
in the following example:
93+
94+
.. code-block:: javascript
95+
96+
db.system.js.save(
97+
{
98+
_id : "myAddFunction" ,
99+
value : function (x, y){ return x + y; }
100+
}
101+
);
102+
103+
- The ``_id`` field holds the name of the function and is unique per
104+
database.
105+
106+
- The ``value`` field holds the function definition
107+
108+
Once you save a function in the ``system.js`` collection, you can use
109+
the function from any JavaScript context (e.g. :ref:`eval
110+
<server-side-eval>`, :ref:`$where <server-side-where>`,
111+
:ref:`map-reduce <server-side-map-reduce>`).
112+
113+
Consider the following example from the :program:`mongo` shell that
114+
first saves a function named ``echoFunction`` to the ``system.js``
115+
collection and calls the function using :ref:`db.eval()
116+
<server-side-eval>`:
117+
118+
.. code-block:: javascript
119+
120+
db.system.js.save(
121+
{ _id: "echoFunction",
122+
value : function(x) { return x; }
123+
}
124+
)
125+
126+
db.eval( "echoFunction( 'test' )" )
127+
128+
See `<http://github.com/mongodb/mongo/tree/master/jstests/storefunc.js>`_ for a full example.
129+
130+
.. versionadded:: 2.1
131+
In the :program:`mongo` shell, you can use
132+
:method:`db.loadServerScripts()` to load all the scripts saved in
133+
the ``system.js`` collection for the current db. Once loaded, you
134+
can invoke the functions directly in the shell, as in the following
135+
example:
136+
137+
.. code-block:: javascript
138+
139+
db.loadServerScripts();
140+
141+
echoFunction(3);
142+
143+
myAddFunction(3, 5);
144+
145+
Concurrency
146+
-----------
147+
148+
Refer to the individual method or operator documentation for any
149+
concurrency information. See also the :ref:`concurrency table
150+
<faq-concurrency-operations-locks>`.

source/faq/concurrency.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ opportunity to complete.
105105
is available in memory, the read will reacquire the lock to
106106
completes the operation.
107107

108+
.. _faq-concurrency-operations-locks:
109+
108110
Which operations lock the database?
109111
-----------------------------------
110112

source/reference/command/eval.txt

Lines changed: 136 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,58 +2,163 @@
22
eval
33
====
44

5+
.. Edits to this page should be carried over to the method db.eval.txt
6+
file.
7+
58
.. default-domain:: mongodb
69

710
.. dbcommand:: eval
811

9-
The :dbcommand:`eval` command evaluates JavaScript functions
10-
on the database server. Consider the following (trivial) example:
12+
The :dbcommand:`eval` command evaluates JavaScript functions on the
13+
database server and has the following form:
14+
15+
.. code-block:: none
16+
17+
{
18+
eval: <function>,
19+
args: [ <arg1>, <arg2> ... ],
20+
nolock: <boolean>
21+
}
22+
23+
The command contains the following fields:
24+
25+
:field JavaScript function:
26+
A JavaScript function to evaluate. The function may
27+
accept no arguments, as in the following example:
28+
29+
.. code-block:: javascript
30+
31+
function () {
32+
33+
...
34+
35+
}
36+
37+
The function can also accept arguments, as in the following example:
38+
39+
.. code-block:: javascript
40+
41+
function (arg1, arg2) {
42+
43+
...
44+
}
45+
46+
If you specify arguments, you must include the corresponding
47+
``args`` field in the command.
48+
49+
:field Array args:
50+
An array of corresponding arguments to the ``function``. Omit
51+
``args`` if the ``function`` does not take arguments.
52+
53+
:field Boolean nolock:
54+
Optional. Specifies whether to disable the write lock. By
55+
default, :dbcommand:`eval` takes a write lock. There are
56+
circumstances where the :dbcommand:`eval` executes a strictly
57+
read-only operation that does not need to block other
58+
operations. If ``nolock`` is ``true``, the
59+
:dbcommand:`eval` does not take a write lock.
60+
61+
.. warning::
62+
63+
Do not disable the write lock if the function may modify
64+
the contents of the database in any way.
65+
66+
Consider the following example which uses :dbcommand:`eval` to
67+
perform an increment and calculate the average on the server:
1168

1269
.. code-block:: javascript
1370

14-
{ eval: function() { return 3+3 } }
71+
db.runCommand( {
72+
eval: function(name, incAmount) {
73+
var doc = db.myCollection.findOne( { name : name } );
74+
75+
doc = doc || { name : name , num : 0 , total : 0 , avg : 0 };
76+
77+
doc.num++;
78+
doc.total += incAmount;
79+
doc.avg = doc.total / doc.num;
80+
81+
db.myCollection.save( doc );
82+
return doc;
83+
},
84+
args: [ "eliot", 5 ]
85+
}
86+
);
1587

16-
The shell also provides a helper method, so you can express the
17-
above as follows:
88+
The ``db`` in the function refers to the current database.
89+
90+
The shell also provides a helper method :method:`db.eval()`, so you
91+
can express the above as follows:
1892

1993
.. code-block:: javascript
2094

21-
db.eval( function() { return 3+3 } );
95+
db.eval( function(name, incAmount) {
96+
var doc = db.myCollection.findOne( { name : name } );
97+
98+
doc = doc || { name : name , num : 0 , total : 0 , avg : 0 };
2299

23-
The shell's JavaScript interpreter evaluates functions entered
24-
directly into the shell. If you want to use the server's
25-
interpreter, you must run :dbcommand:`eval`.
100+
doc.num++;
101+
doc.total += incAmount;
102+
doc.avg = doc.total / doc.num;
103+
104+
db.myCollection.save( doc );
105+
return doc;
106+
},
107+
"eliot", 5 );
26108

27-
Be aware of following behaviors and limitations:
109+
You cannot pass the ``nolock`` flag to the :method:`db.eval()`
110+
in the :program:`mongo` shell.
28111

29-
- :dbcommand:`eval` does not work in :term:`sharded <sharding>`
30-
environments.
112+
If you want to use the server's interpreter, you must run
113+
:dbcommand:`eval`. Otherwise, the :program:`mongo` shell's
114+
JavaScript interpreter evaluates functions entered directly into the
115+
shell.
31116

32-
- The ``eval`` operation take a write lock by default. This means
33-
that writes to database aren't permitted while it's running. You
34-
can, however, disable the lock by setting the ``nolock`` flag to
35-
``true``. For example:
117+
If an error occurs, :dbcommand:`eval` throws an exception. Consider
118+
the following invalid function that uses the variable ``x`` without
119+
declaring it as an argument:
120+
121+
.. code-block:: javascript
36122

37-
.. code-block:: javascript
123+
db.runCommand(
124+
{
125+
eval: function() { return x + x; },
126+
args: [3]
127+
}
128+
)
129+
130+
The statement will result in the following exception:
131+
132+
.. code-block:: javascript
38133

39-
{ eval: function() { return 3+3 }, nolock: true }
134+
{
135+
"errno" : -3,
136+
"errmsg" : "invoke failed: JS Error: ReferenceError: x is not defined nofile_b:1",
137+
"ok" : 0
138+
}
40139

41-
Using :method:`db.runCommand()` helper, in the :program:`mongo`
42-
shell, this command would resemble:
140+
.. warning::
43141

44-
.. code-block:: javascript
142+
- The :dbcommand:`eval` operation takes a write lock by default.
143+
This means that other read and write operations to the database
144+
are blocked while :dbcommand:`eval` is running. You can,
145+
however, disable the lock by setting the ``nolock`` flag to
146+
``true`` if the ``eval`` performs a strictly read-only
147+
operation.
45148

46-
db.runCommand( { eval: function() { return 3+3 }, nolock: true } )
149+
- :dbcommand:`eval` also takes a JavaScript lock.
47150

48-
.. warning::
151+
- Do not use :dbcommand:`eval` for long running operations as
152+
:dbcommand:`eval` blocks all other operations. Consider using
153+
:doc:`other server side code execution options
154+
</applications/server-side-code-execution>`.
49155

50-
Do not disable the write lock if the operation may modify the
51-
contents of the database in anyway.
156+
- You can not use :dbcommand:`eval` with :term:`sharded
157+
<sharding>` data. In general, you should avoid using
158+
:dbcommand:`eval` in :term:`sharded cluster`; nevertheless, it
159+
is possible to use :dbcommand:`eval` with non-sharded
160+
collections and databases stored in a :term:`sharded cluster`.
52161

53-
You cannot pass the ``nolock`` option to :method:`db.eval()` in
54-
the :program:`mongo` shell.
162+
.. seealso::
55163

56-
There are some circumstances where the :method:`db.eval()`
57-
implements a strictly-read only operation that need not block
58-
other operations when disabling the write lock may be useful. Use
59-
this functionality with extreme caution.
164+
:doc:`/applications/server-side-code-execution`

0 commit comments

Comments
 (0)