forked from meteor/meteor
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapi.html
More file actions
3580 lines (2729 loc) · 136 KB
/
api.html
File metadata and controls
3580 lines (2729 loc) · 136 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<template name="api">
{{#markdown}}
<h1 id="api">The Meteor API</h1>
Your JavaScript code can run in two environments: the *client* (browser), and
the *server* (a [Node.js](http://nodejs.org/) container on a server). For each
function in this API reference, we'll indicate if the function is available just
on the client, just on the server, or *Anywhere*.
<h2 id="core"><span>Meteor Core</span></h2>
{{> autoApiBox "Meteor.isClient"}}
{{> autoApiBox "Meteor.isServer"}}
{{#note}}
`Meteor.isServer` can be used to limit where code runs, but it does not
prevent code from being sent to the client. Any sensitive code that you
don't want served to the client, such as code containing passwords or
authentication mechanisms, should be kept in the `server` directory.
{{/note}}
{{> api_box isCordova}}
{{> autoApiBox "Meteor.startup"}}
On a server, the function will run as soon as the server process is
finished starting. On a client, the function will run as soon as the DOM
is ready.
The `startup` callbacks are called in the same order as the calls to
`Meteor.startup` were made.
On a client, `startup` callbacks from packages will be called
first, followed by `<body>` templates from your `.html` files,
followed by your application code.
// On server startup, if the database is empty, create some initial data.
if (Meteor.isServer) {
Meteor.startup(function () {
if (Rooms.find().count() === 0) {
Rooms.insert({name: "Initial room"});
}
});
}
{{> api_box wrapAsync}}
{{> autoApiBox "Meteor.absoluteUrl"}}
{{> autoApiBox "Meteor.settings"}}
{{> autoApiBox "Meteor.release"}}
<h2 id="publishandsubscribe"><span>Publish and subscribe</span></h2>
These functions control how Meteor servers publish sets of records and
how clients can subscribe to those sets.
{{> autoApiBox "Meteor.publish"}}
To publish records to clients, call `Meteor.publish` on the server with
two parameters: the name of the record set, and a *publish function*
that Meteor will call each time a client subscribes to the name.
Publish functions can return a
[`Collection.Cursor`](#mongo_cursor), in which case Meteor
will publish that cursor's documents to each subscribed client. You can
also return an array of `Collection.Cursor`s, in which case Meteor will
publish all of the cursors.
{{#warning}}
If you return multiple cursors in an array, they currently must all be from
different collections. We hope to lift this restriction in a future release.
{{/warning}}
// server: publish the rooms collection, minus secret info.
Meteor.publish("rooms", function () {
return Rooms.find({}, {fields: {secretInfo: 0}});
});
// ... and publish secret info for rooms where the logged-in user
// is an admin. If the client subscribes to both streams, the records
// are merged together into the same documents in the Rooms collection.
Meteor.publish("adminSecretInfo", function () {
return Rooms.find({admin: this.userId}, {fields: {secretInfo: 1}});
});
// publish dependent documents and simulate joins
Meteor.publish("roomAndMessages", function (roomId) {
check(roomId, String);
return [
Rooms.find({_id: roomId}, {fields: {secretInfo: 0}}),
Messages.find({roomId: roomId})
];
});
Alternatively, a publish function can directly control its published record set
by calling the functions [`added`](#publish_added) (to add a new document to the
published record set), [`changed`](#publish_changed) (to change or clear some
fields on a document already in the published record set), and
[`removed`](#publish_removed) (to remove documents from the published record
set). These methods are provided by `this` in your publish function.
If a publish function does not return a cursor or array of cursors, it is
assumed to be using the low-level `added`/`changed`/`removed` interface, and it
**must also call [`ready`](#publish_ready) once the initial record set is
complete**.
Example:
// server: publish the current size of a collection
Meteor.publish("counts-by-room", function (roomId) {
var self = this;
check(roomId, String);
var count = 0;
var initializing = true;
// observeChanges only returns after the initial `added` callbacks
// have run. Until then, we don't want to send a lot of
// `self.changed()` messages - hence tracking the
// `initializing` state.
var handle = Messages.find({roomId: roomId}).observeChanges({
added: function (id) {
count++;
if (!initializing)
self.changed("counts", roomId, {count: count});
},
removed: function (id) {
count--;
self.changed("counts", roomId, {count: count});
}
// don't care about changed
});
// Instead, we'll send one `self.added()` message right after
// observeChanges has returned, and mark the subscription as
// ready.
initializing = false;
self.added("counts", roomId, {count: count});
self.ready();
// Stop observing the cursor when client unsubs.
// Stopping a subscription automatically takes
// care of sending the client any removed messages.
self.onStop(function () {
handle.stop();
});
});
// client: declare collection to hold count object
Counts = new Mongo.Collection("counts");
// client: subscribe to the count for the current room
Tracker.autorun(function () {
Meteor.subscribe("counts-by-room", Session.get("roomId"));
});
// client: use the new collection
console.log("Current room has " +
Counts.findOne(Session.get("roomId")).count +
" messages.");
// server: sometimes publish a query, sometimes publish nothing
Meteor.publish("secretData", function () {
if (this.userId === 'superuser') {
return SecretData.find();
} else {
// Declare that no data is being published. If you leave this line
// out, Meteor will never consider the subscription ready because
// it thinks you're using the added/changed/removed interface where
// you have to explicitly call this.ready().
return [];
}
});
{{#warning}}
Meteor will emit a warning message if you call `Meteor.publish` in a
project that includes the `autopublish` package. Your publish function
will still work.
{{/warning}}
{{> autoApiBox "Subscription#userId"}}
This is constant. However, if the logged-in user changes, the publish
function is rerun with the new value.
{{> autoApiBox "Subscription#added"}}
{{> autoApiBox "Subscription#changed"}}
{{> autoApiBox "Subscription#removed"}}
{{> autoApiBox "Subscription#ready"}}
{{> autoApiBox "Subscription#onStop"}}
If you call [`observe`](#observe) or [`observeChanges`](#observe_changes) in your
publish handler, this is the place to stop the observes.
{{> autoApiBox "Subscription#error"}}
{{> autoApiBox "Subscription#stop"}}
{{> autoApiBox "Subscription#connection"}}
{{> api_box subscribe}}
When you subscribe to a record set, it tells the server to send records to the
client. The client stores these records in local [Minimongo
collections](#mongo_collection), with the same name as the `collection`
argument used in the publish handler's [`added`](#publish_added),
[`changed`](#publish_changed), and [`removed`](#publish_removed)
callbacks. Meteor will queue incoming records until you declare the
[`Mongo.Collection`](#mongo_collection) on the client with the matching
collection name.
// okay to subscribe (and possibly receive data) before declaring
// the client collection that will hold it. assume "allplayers"
// publishes data from server's "players" collection.
Meteor.subscribe("allplayers");
...
// client queues incoming players records until ...
...
Players = new Mongo.Collection("players");
The client will see a document if the document is currently in the published
record set of any of its subscriptions.
The `onReady` callback is called with no arguments when the server
[marks the subscription as ready](#publish_ready). The `onError` callback is
called with a [`Meteor.Error`](#meteor_error) if the subscription fails or is
terminated by the server.
`Meteor.subscribe` returns a subscription handle, which is an object with the
following methods:
<dl class="callbacks">
{{#dtdd "stop()"}}
Cancel the subscription. This will typically result in the server directing the
client to remove the subscription's data from the client's cache.
{{/dtdd}}
{{#dtdd "ready()"}}
True if the server has [marked the subscription as ready](#publish_ready). A
reactive data source.
{{/dtdd}}
</dl>
If you call `Meteor.subscribe` within a [reactive computation](#reactivity),
for example using
[`Tracker.autorun`](#tracker_autorun), the subscription will automatically be
cancelled when the computation is invalidated or stopped; it's not necessary
to call `stop` on
subscriptions made from inside `autorun`. However, if the next iteration
of your run function subscribes to the same record set (same name and
parameters), Meteor is smart enough to skip a wasteful
unsubscribe/resubscribe. For example:
Tracker.autorun(function () {
Meteor.subscribe("chat", {room: Session.get("current-room")});
Meteor.subscribe("privateMessages");
});
This subscribes you to the chat messages in the current room and to your private
messages. When you change rooms by calling `Session.set("current-room",
"new-room")`, Meteor will subscribe to the new room's chat messages,
unsubscribe from the original room's chat messages, and continue to
stay subscribed to your private messages.
If more than one subscription sends conflicting values for a field (same
collection name, document ID, and field name), then the value on the client will
be one of the published values, chosen arbitrarily.
<h2 id="methods_header"><span>Methods</span></h2>
Methods are remote functions that Meteor clients can invoke.
{{> autoApiBox "Meteor.methods"}}
Example:
Meteor.methods({
foo: function (arg1, arg2) {
check(arg1, String);
check(arg2, [Number]);
// .. do stuff ..
if (you want to throw an error)
throw new Meteor.Error(404, "Can't find my pants");
return "some return value";
},
bar: function () {
// .. do other stuff ..
return "baz";
}
});
Calling `methods` on the server defines functions that can be called remotely by
clients. They should return an [EJSON](#ejson)-able value or throw an
exception. Inside your method invocation, `this` is bound to a method
invocation object, which provides the following:
* `isSimulation`: a boolean value, true if this invocation is a stub.
* `unblock`: when called, allows the next method from this client to
begin running.
* `userId`: the id of the current user.
* `setUserId`: a function that associates the current client with a user.
* `connection`: on the server, the [connection](#meteor_onconnection) this method call was received on.
Calling `methods` on the client defines *stub* functions associated with
server methods of the same name. You don't have to define a stub for
your method if you don't want to. In that case, method calls are just
like remote procedure calls in other systems, and you'll have to wait
for the results from the server.
If you do define a stub, when a client invokes a server method it will
also run its stub in parallel. On the client, the return value of a
stub is ignored. Stubs are run for their side-effects: they are
intended to *simulate* the result of what the server's method will do,
but without waiting for the round trip delay. If a stub throws an
exception it will be logged to the console.
You use methods all the time, because the database mutators
([`insert`](#insert), [`update`](#update), [`remove`](#remove)) are implemented
as methods. When you call any of these functions on the client, you're invoking
their stub version that update the local cache, and sending the same write
request to the server. When the server responds, the client updates the local
cache with the writes that actually occurred on the server.
{{> autoApiBox "MethodInvocation#userId"}}
The user id is an arbitrary string — typically the id of the user record
in the database. You can set it with the `setUserId` function. If you're using
the [Meteor accounts system](#accounts_api) then this is handled for you.
{{> autoApiBox "MethodInvocation#setUserId"}}
Call this function to change the currently logged in user on the
connection that made this method call. This simply sets the value of
`userId` for future method calls received on this connection. Pass
`null` to log out the connection.
If you are using the [built-in Meteor accounts system](#accounts_api) then this
should correspond to the `_id` field of a document in the
[`Meteor.users`](#meteor_users) collection.
`setUserId` is not retroactive. It affects the current method call and
any future method calls on the connection. Any previous method calls on
this connection will still see the value of `userId` that was in effect
when they started.
{{> autoApiBox "MethodInvocation#isSimulation"}}
{{> autoApiBox "MethodInvocation#unblock"}}
On the server, methods from a given client run one at a time. The N+1th
invocation from a client won't start until the Nth invocation
returns. However, you can change this by calling `this.unblock`. This
will allow the N+1th invocation to start running in a new fiber.
{{> autoApiBox "MethodInvocation#connection"}}
{{> autoApiBox "Meteor.Error"}}
If you want to return an error from a method, throw an exception. Methods can
throw any kind of exception. But `Meteor.Error` is the only kind of error that
a server will send to the client. If a method function throws a different
exception, then it will be mapped to a sanitized version on the
wire. Specifically, if the `sanitizedError` field on the thrown error is set to
a `Meteor.Error`, then that error will be sent to the client. Otherwise, if no
sanitized version is available, the client gets
`Meteor.Error(500, 'Internal server error')`.
{{> api_box meteor_call}}
This is how to invoke a method. It will run the method on the server. If a
stub is available, it will also run the stub on the client. (See also
[`Meteor.apply`](#meteor_apply), which is identical to `Meteor.call` except that
you specify the parameters as an array instead of as separate arguments and you
can specify a few options controlling how the method is executed.)
If you include a callback function as the last argument (which can't be
an argument to the method, since functions aren't serializable), the
method will run asynchronously: it will return nothing in particular and
will not throw an exception. When the method is complete (which may or
may not happen before `Meteor.call` returns), the callback will be
called with two arguments: `error` and `result`. If an error was thrown,
then `error` will be the exception object. Otherwise, `error` will be
undefined and the return value (possibly undefined) will be in `result`.
// async call
Meteor.call('foo', 1, 2, function (error, result) { ... } );
If you do not pass a callback on the server, the method invocation will
block until the method is complete. It will eventually return the
return value of the method, or it will throw an exception if the method
threw an exception. (Possibly mapped to 500 Server Error if the
exception happened remotely and it was not a `Meteor.Error` exception.)
// sync call
var result = Meteor.call('foo', 1, 2);
On the client, if you do not pass a callback and you are not inside a
stub, `call` will return `undefined`, and you will have no way to get
the return value of the method. That is because the client doesn't have
fibers, so there is not actually any way it can block on the remote
execution of a method.
Finally, if you are inside a stub on the client and call another
method, the other method is not executed (no RPC is generated, nothing
"real" happens). If that other method has a stub, that stub stands in
for the method and is executed. The method call's return value is the
return value of the stub function. The client has no problem executing
a stub synchronously, and that is why it's okay for the client to use
the synchronous `Meteor.call` form from inside a method body, as
described earlier.
Meteor tracks the database writes performed by methods, both on the client and
the server, and does not invoke `asyncCallback` until all of the server's writes
replace the stub's writes in the local cache. In some cases, there can be a lag
between the method's return value being available and the writes being visible:
for example, if another method still outstanding wrote to the same document, the
local cache may not be up to date until the other method finishes as well. If
you want to process the method's result as soon as it arrives from the server,
even if the method's writes are not available yet, you can specify an
`onResultReceived` callback to [`Meteor.apply`](#meteor_apply).
{{> api_box meteor_apply}}
`Meteor.apply` is just like `Meteor.call`, except that the method arguments are
passed as an array rather than directly as arguments, and you can specify
options about how the client executes the method.
<h2 id="connections"><span>Server connections</span></h2>
These functions manage and inspect the network connection between the
Meteor client and server.
{{> autoApiBox "Meteor.status"}}
This method returns the status of the connection between the client and
the server. The return value is an object with the following fields:
<dl class="objdesc">
{{#dtdd name="connected" type="Boolean"}}
True if currently connected to the server. If false, changes and
method invocations will be queued up until the connection is
reestablished.
{{/dtdd}}
{{#dtdd name="status" type="String"}}
Describes the current reconnection status. The possible
values are `connected` (the connection is up and
running), `connecting` (disconnected and trying to open a
new connection), `failed` (permanently failed to connect; e.g., the client
and server support different versions of DDP), `waiting` (failed
to connect and waiting to try to reconnect) and `offline` (user has disconnected the connection).
{{/dtdd}}
{{#dtdd name="retryCount" type="Number"}}
The number of times the client has tried to reconnect since the
connection was lost. 0 when connected.
{{/dtdd}}
{{#dtdd name="retryTime" type="Number or undefined"}}
The estimated time of the next reconnection attempt. To turn this
into an interval until the next reconnection, use
`retryTime - (new Date()).getTime()`. This key will
be set only when `status` is `waiting`.
{{/dtdd}}
{{#dtdd name="reason" type="String or undefined"}}
If `status` is `failed`, a description of why the connection failed.
{{/dtdd}}
</dl>
Instead of using callbacks to notify you on changes, this is
a [reactive](#reactivity) data source. You can use it in a
[template](#livehtmltemplates) or [computation](#tracker_autorun)
to get realtime updates.
{{> autoApiBox "Meteor.reconnect"}}
{{> autoApiBox "Meteor.disconnect"}}
Call this method to disconnect from the server and stop all
live data updates. While the client is disconnected it will not receive
updates to collections, method calls will be queued until the
connection is reestablished, and hot code push will be disabled.
Call [Meteor.reconnect](#meteor_reconnect) to reestablish the connection
and resume data transfer.
This can be used to save battery on mobile devices when real time
updates are not required.
{{> autoApiBox "Meteor.onConnection"}}
`onConnection` returns an object with a single method `stop`. Calling
`stop` unregisters the callback, so that this callback will no longer
be called on new connections.
The callback is called with a single argument, the server-side
`connection` representing the connection from the client. This object
contains the following fields:
<dl class="objdesc">
{{#dtdd name="id" type="String"}}
A globally unique id for this connection.
{{/dtdd}}
{{#dtdd name="close" type="Function"}}
Close this DDP connection. The client is free to reconnect, but will
receive a different connection with a new `id` if it does.
{{/dtdd}}
{{#dtdd name="onClose" type="Function"}}
Register a callback to be called when the connection is closed. If the
connection is already closed, the callback will be called immediately.
{{/dtdd}}
{{#dtdd name="clientAddress" type="String"}}
The IP address of the client in dotted form (such as `"127.0.0.1"`).
If you're running your Meteor server behind a proxy (so that clients
are connecting to the proxy instead of to your server directly),
you'll need to set the `HTTP_FORWARDED_COUNT` environment variable
for the correct IP address to be reported by `clientAddress`.
Set `HTTP_FORWARDED_COUNT` to an integer representing the number of
proxies in front of your server. For example, you'd set it to `"1"`
when your server was behind one proxy.
{{/dtdd}}
{{#dtdd name="httpHeaders" type="Object"}}
When the connection came in over an HTTP transport (such as with
Meteor's default SockJS implementation), this field contains
whitelisted HTTP headers.
Cookies are deliberately excluded from the headers as they are a
security risk for this transport. For details and alternatives, see
the [SockJS
documentation](https://github.com/sockjs/sockjs-node#authorisation).
{{/dtdd}}
</dl>
{{#note}}
Currently when a client reconnects to the server (such as after
temporarily losing its Internet connection), it will get a new
connection each time. The `onConnection` callbacks will be called
again, and the new connection will have a new connection `id`.
In the future, when client reconnection is fully implemented,
reconnecting from the client will reconnect to the same connection on
the server: the `onConnection` callback won't be called for that
connection again, and the connection will still have the same
connection `id`.
{{/note}}
{{> autoApiBox "DDP.connect"}}
To call methods on another Meteor application or subscribe to its data
sets, call `DDP.connect` with the URL of the application.
`DDP.connect` returns an object which provides:
* `subscribe` -
Subscribe to a record set. See
[Meteor.subscribe](#meteor_subscribe).
* `call` -
Invoke a method. See [Meteor.call](#meteor_call).
* `apply` -
Invoke a method with an argument array. See
[Meteor.apply](#meteor_apply).
* `methods` -
Define client-only stubs for methods defined on the remote server. See
[Meteor.methods](#meteor_methods).
* `status` -
Get the current connection status. See
[Meteor.status](#meteor_status).
* `reconnect` -
See [Meteor.reconnect](#meteor_reconnect).
* `disconnect` -
See [Meteor.disconnect](#meteor_disconnect).
* `onReconnect` - Set this to a function to be called as the first step of
reconnecting. This function can call methods which will be executed before
any other outstanding methods. For example, this can be used to re-establish
the appropriate authentication context on the new connection.
By default, clients open a connection to the server from which they're loaded.
When you call `Meteor.subscribe`, `Meteor.status`, `Meteor.call`, and
`Meteor.apply`, you are using a connection back to that default
server.
<h2 id="collections"><span>Collections</span></h2>
Meteor stores data in *collections*. To get started, declare a
collection with `new Mongo.Collection`.
{{> autoApiBox "Mongo.Collection"}}
Calling this function is analogous to declaring a model in a traditional ORM
(Object-Relation Mapper)-centric framework. It sets up a *collection* (a storage
space for records, or "documents") that can be used to store a particular type
of information, like users, posts, scores, todo items, or whatever matters to
your application. Each document is a EJSON object. It includes an `_id`
property whose value is unique in the collection, which Meteor will set when you
first create the document.
// common code on client and server declares a DDP-managed mongo
// collection.
Chatrooms = new Mongo.Collection("chatrooms");
Messages = new Mongo.Collection("messages");
The function returns an object with methods to [`insert`](#insert)
documents in the collection, [`update`](#update) their properties, and
[`remove`](#remove) them, and to [`find`](#find) the documents in the
collection that match arbitrary criteria. The way these methods work is
compatible with the popular Mongo database API. The same database API
works on both the client and the server (see below).
// return array of my messages
var myMessages = Messages.find({userId: Session.get('myUserId')}).fetch();
// create a new message
Messages.insert({text: "Hello, world!"});
// mark my first message as "important"
Messages.update(myMessages[0]._id, {$set: {important: true}});
If you pass a `name` when you create the collection, then you are
declaring a persistent collection — one that is stored on the
server and seen by all users. Client code and server code can both
access the same collection using the same API.
Specifically, when you pass a `name`, here's what happens:
* On the server (if you do not specify a `connection`), a collection with that
name is created on a backend Mongo server. When you call methods on that
collection on the server, they translate directly into normal Mongo operations
(after checking that they match your [access control rules](#allow)).
* On the client (and on the server if you specify a `connection`), a Minimongo
instance is created. Minimongo is essentially an in-memory, non-persistent
implementation of Mongo in pure JavaScript. It serves as a local cache that
stores just the subset of the database that this client is working with. Queries
([`find`](#find)) on these collections are served directly out of this cache,
without talking to the server.
* When you write to the database on the client ([`insert`](#insert),
[`update`](#update), [`remove`](#remove)), the command is executed locally
immediately, and, simultaneously, it's sent to the server and executed
there too. This happens via [stubs](#meteor_methods), because writes are
implemented as methods.
{{#note}}
When, on the server, you write to a collection which has a specified
`connection` to another server, it sends the corresponding method to the other
server and receives the changed values back from it over DDP. Unlike on the
client, it does not execute the write locally first.
{{/note}}
If you pass `null` as the `name`, then you're creating a local
collection. It's not synchronized anywhere; it's just a local scratchpad
that supports Mongo-style [`find`](#find), [`insert`](#insert),
[`update`](#update), and [`remove`](#remove) operations. (On both the
client and the server, this scratchpad is implemented using Minimongo.)
By default, Meteor automatically publishes every document in your
collection to each connected client. To turn this behavior off, remove
the `autopublish` package:
$ meteor remove autopublish
and instead call [`Meteor.publish`](#meteor_publish) to specify which parts of
your collection should be published to which users.
// Create a collection called Posts and put a document in it. The
// document will be immediately visible in the local copy of the
// collection. It will be written to the server-side database
// a fraction of a second later, and a fraction of a second
// after that, it will be synchronized down to any other clients
// that are subscribed to a query that includes it (see
// Meteor.subscribe and autopublish)
Posts = new Mongo.Collection("posts");
Posts.insert({title: "Hello world", body: "First post"});
// Changes are visible immediately -- no waiting for a round trip to
// the server.
assert(Posts.find().count() === 1);
// Create a temporary, local collection. It works just like any other
// collection, but it doesn't send changes to the server, and it
// can't receive any data from subscriptions.
Scratchpad = new Mongo.Collection;
for (var i = 0; i < 10; i++)
Scratchpad.insert({number: i * 2});
assert(Scratchpad.find({number: {$lt: 9}}).count() === 5);
Generally, you'll assign `Mongo.Collection` objects in your app to global
variables. You can only create one `Mongo.Collection` object for each
underlying Mongo collection.
If you specify a `transform` option to the `Collection` or any of its retrieval
methods, documents are passed through the `transform` function before being
returned or passed to callbacks. This allows you to add methods or otherwise
modify the contents of your collection from their database representation. You
can also specify `transform` on a particular `find`, `findOne`, `allow`, or
`deny` call. Transform functions must return an object and they may not change
the value of the document's `_id` field (though it's OK to leave it out).
// An Animal class that takes a document in its constructor
Animal = function (doc) {
_.extend(this, doc);
};
_.extend(Animal.prototype, {
makeNoise: function () {
console.log(this.sound);
}
});
// Define a Collection that uses Animal as its document
Animals = new Mongo.Collection("Animals", {
transform: function (doc) { return new Animal(doc); }
});
// Create an Animal and call its makeNoise method
Animals.insert({name: "raptor", sound: "roar"});
Animals.findOne({name: "raptor"}).makeNoise(); // prints "roar"
`transform` functions are not called reactively. If you want to add a
dynamically changing attribute to an object, do it with a function that computes
the value at the time it's called, not by computing the attribute at `transform`
time.
{{#warning}}
In this release, Minimongo has some limitations:
* `$pull` in modifiers can only accept certain kinds
of selectors.
* `findAndModify`, aggregate functions, and
map/reduce aren't supported.
All of these will be addressed in a future release. For full
Minimongo release notes, see packages/minimongo/NOTES
in the repository.
{{/warning}}
{{#warning}}
Minimongo doesn't currently have indexes. It's rare for this to be an
issue, since it's unusual for a client to have enough data that an
index is worthwhile.
{{/warning}}
{{> autoApiBox "Mongo.Collection#find"}}
`find` returns a cursor. It does not immediately access the database or return
documents. Cursors provide `fetch` to return all matching documents, `map` and
`forEach` to iterate over all matching documents, and `observe` and
`observeChanges` to register callbacks when the set of matching documents
changes.
{{#warning}}
Collection cursors are not query snapshots. If the database changes
between calling `Collection.find` and fetching the
results of the cursor, or while fetching results from the cursor,
those changes may or may not appear in the result set.
{{/warning}}
Cursors are a reactive data source. On the client, the first time you retrieve a
cursor's documents with `fetch`, `map`, or `forEach` inside a
reactive computation (eg, a template or
[`autorun`](#tracker_autorun)), Meteor will register a
dependency on the underlying data. Any change to the collection that
changes the documents in a cursor will trigger a recomputation. To
disable this behavior, pass `{reactive: false}` as an option to
`find`.
Note that when `fields` are specified, only changes to the included
fields will trigger callbacks in `observe`, `observeChanges` and
invalidations in reactive computations using this cursor. Careful use
of `fields` allows for more fine-grained reactivity for computations
that don't depend on an entire document.
{{> autoApiBox "Mongo.Collection#findOne"}}
Equivalent to `find(selector, options).fetch()[0]` with
`options.limit = 1`.
{{> autoApiBox "Mongo.Collection#insert"}}
Add a document to the collection. A document is just an object, and
its fields can contain any combination of EJSON-compatible datatypes
(arrays, objects, numbers, strings, `null`, true, and false).
`insert` will generate a unique ID for the object you pass, insert it
in the database, and return the ID. When `insert` is called from
untrusted client code, it will be allowed only if passes any
applicable [`allow`](#allow) and [`deny`](#deny) rules.
On the server, if you don't provide a callback, then `insert` blocks
until the database acknowledges the write, or throws an exception if
something went wrong. If you do provide a callback, `insert` still
returns the ID immediately. Once the insert completes (or fails), the
callback is called with error and result arguments. In an error case,
`result` is undefined. If the insert is successful, `error` is
undefined and `result` is the new document ID.
On the client, `insert` never blocks. If you do not provide a callback
and the insert fails on the server, then Meteor will log a warning to
the console. If you provide a callback, Meteor will call that function
with `error` and `result` arguments. In an error case, `result` is
undefined. If the insert is successful, `error` is undefined and
`result` is the new document ID.
Example:
var groceriesId = Lists.insert({name: "Groceries"});
Items.insert({list: groceriesId, name: "Watercress"});
Items.insert({list: groceriesId, name: "Persimmons"});
{{> autoApiBox "Mongo.Collection#update"}}
Modify documents that match `selector` according to `modifier` (see
[modifier documentation](#modifiers)).
The behavior of `update` differs depending on whether it is called by
trusted or untrusted code. Trusted code includes server code and
method code. Untrusted code includes client-side code such as event
handlers and a browser's JavaScript console.
- Trusted code can modify multiple documents at once by setting
`multi` to true, and can use an arbitrary [Mongo
selector](#selectors) to find the documents to modify. It bypasses
any access control rules set up by [`allow`](#allow) and
[`deny`](#deny). The number of affected documents will be returned
from the `update` call if you don't pass a callback.
- Untrusted code can only modify a single document at once, specified
by its `_id`. The modification is allowed only after checking any
applicable [`allow`](#allow) and [`deny`](#deny) rules. The number
of affected documents will be returned to the callback. Untrusted
code cannot perform upserts, except in insecure mode.
On the server, if you don't provide a callback, then `update` blocks
until the database acknowledges the write, or throws an exception if
something went wrong. If you do provide a callback, `update` returns
immediately. Once the update completes, the callback is called with a
single error argument in the case of failure, or a second argument
indicating the number of affected documents if the update was successful.
On the client, `update` never blocks. If you do not provide a callback
and the update fails on the server, then Meteor will log a warning to
the console. If you provide a callback, Meteor will call that function
with an error argument if there was an error, or a second argument
indicating the number of affected documents if the update was successful.
Client example:
// When the givePoints button in the admin dashboard is pressed,
// give 5 points to the current player. The new score will be
// immediately visible on everyone's screens.
Template.adminDashboard.events({
'click .givePoints': function () {
Players.update(Session.get("currentPlayer"), {$inc: {score: 5}});
}
});
Server example:
// Give the "Winner" badge to each user with a score greater than
// 10. If they are logged in and their badge list is visible on the
// screen, it will update automatically as they watch.
Meteor.methods({
declareWinners: function () {
Players.update({score: {$gt: 10}},
{$addToSet: {badges: "Winner"}},
{multi: true});
}
});
You can use `update` to perform a Mongo upsert by setting the `upsert`
option to true. You can also use the [`upsert`](#upsert) method to perform an
upsert that returns the _id of the document that was inserted (if there was one)
in addition to the number of affected documents.
{{> autoApiBox "Mongo.Collection#upsert"}}
Modify documents that match `selector` according to `modifier`, or insert
a document if no documents were modified. `upsert` is the same as calling
`update` with the `upsert` option set to true, except that the return
value of `upsert` is an object that contain the keys `numberAffected`
and `insertedId`. (`update` returns only the number of affected documents.)
{{> autoApiBox "Mongo.Collection#remove"}}
Find all of the documents that match `selector` and delete them from
the collection.
The behavior of `remove` differs depending on whether it is called by
trusted or untrusted code. Trusted code includes server code and
method code. Untrusted code includes client-side code such as event
handlers and a browser's JavaScript console.
- Trusted code can use an arbitrary [Mongo selector](#selectors) to
find the documents to remove, and can remove more than one document
at once by passing a selector that matches multiple documents. It
bypasses any access control rules set up by [`allow`](#allow) and
[`deny`](#deny). The number of removed documents will be returned
from `remove` if you don't pass a callback.
As a safety measure, if `selector` is omitted (or is `undefined`),
no documents will be removed. Set `selector` to `{}` if you really
want to remove all documents from your collection.
- Untrusted code can only remove a single document at a time,
specified by its `_id`. The document is removed only after checking
any applicable [`allow`](#allow) and [`deny`](#deny) rules. The
number of removed documents will be returned to the callback.
On the server, if you don't provide a callback, then `remove` blocks
until the database acknowledges the write and then returns the number
of removed documents, or throws an exception if
something went wrong. If you do provide a callback, `remove` returns
immediately. Once the remove completes, the callback is called with a
single error argument in the case of failure, or a second argument
indicating the number of removed documents if the remove was successful.
On the client, `remove` never blocks. If you do not provide a callback
and the remove fails on the server, then Meteor will log a warning to the
console. If you provide a callback, Meteor will call that function with an
error argument if there was an error, or a second argument indicating the number
of removed documents if the remove was successful.
Client example:
// When the remove button is clicked on a chat message, delete
// that message.
Template.chat.events({
'click .remove': function () {
Messages.remove(this._id);
}
});
Server example:
// When the server starts, clear the log, and delete all players
// with a karma of less than -2.
Meteor.startup(function () {
if (Meteor.isServer) {
Logs.remove({});
Players.remove({karma: {$lt: -2}});
}
});
{{> api_box allow}}
When a client calls `insert`, `update`, or `remove` on a collection, the
collection's `allow` and [`deny`](#deny) callbacks are called
on the server to determine if the write should be allowed. If at least
one `allow` callback allows the write, and no `deny` callbacks deny the
write, then the write is allowed to proceed.
These checks are run only when a client tries to write to the database
directly, for example by calling `update` from inside an event
handler. Server code is trusted and isn't subject to `allow` and `deny`
restrictions. That includes methods that are called with `Meteor.call`
— they are expected to do their own access checking rather than
relying on `allow` and `deny`.
You can call `allow` as many times as you like, and each call can
include any combination of `insert`, `update`, and `remove`
functions. The functions should return `true` if they think the
operation should be allowed. Otherwise they should return `false`, or
nothing at all (`undefined`). In that case Meteor will continue
searching through any other `allow` rules on the collection.
The available callbacks are:
<dl class="callbacks">
{{#dtdd "insert(userId, doc)"}}
The user `userId` wants to insert the document `doc` into the
collection. Return `true` if this should be allowed.
`doc` will contain the `_id` field if one was explicitly set by the client, or
if there is an active `transform`. You can use this to prevent users from
specifying arbitrary `_id` fields.
{{/dtdd}}
{{#dtdd "update(userId, doc, fieldNames, modifier)"}}
The user `userId` wants to update a document `doc`. (`doc` is the
current version of the document from the database, without the
proposed update.) Return `true` to permit the change.
`fieldNames` is an array of the (top-level) fields in `doc` that the
client wants to modify, for example
`['name',` `'score']`.
`modifier` is the raw Mongo modifier that
the client wants to execute; for example,
`{$set: {'name.first': "Alice"}, $inc: {score: 1}}`.