How can I make changes on my Collections locally (minimongo)? - meteor

What to do when I want to make changes on my data Collection but I do not want to persist it? In other words, I want to make changes on minimongo, locally, but I do not want to spread it to world.

Use _collection.
MyCollection = new Meteor.Collection('my-collection');
// Subscribe as you see fit
Meteor.subscribe('my-publication');
// Now, to make updates locally you can access the documents in the collection without
// making any calls to the sever.
MyCollection._collection.insert({key:value});
MyCollection._collection.update({key:value}, {key:value});
Works with the usual mini-mongo operations.
This is undocumented and might change in future releases of Meteor without notice.

According to the docs, we can create a Collection and set its name as null. It will create an unmanaged (unsynchronized) local collection.
Unfortunately, it seems to not be possible to make local changes in synchronized collections.

You can create what I call a "local mirror" of a shared collection. Here's a gist with baisc functionality: https://gist.github.com/belisarius222/4715531
The idea is that you wire up a new local collection (new Meteor.Collection(null)) so that any change in the shared collection gets applied to the local collection too.

Related

How do you manage adding new attributes on existing objects when using firebase?

I have an app using React + Redux and coupled with Firebase for the backend.
Often times, I will want to add some new attributes to existing objects.
When doing so, existing objects won't get the attribute until they're modified with the new version of the app that handles those new attributes.
For example, let's say I have a /categories/ node, in there I've got objects such as this :
{
name: "Medical"
}
Now let's say I want to add an icon field with a default of "
Is it possible to update all categories at once so that field always exists with the default value?
Or do you handle this in the client code?
Right now I'm always testing the values to see if they're here or not, but it doesn't seem like a very good way to go about it. I'd like to have one place to define defaults.
It seems like having classes for each object type would be interesting but I'm not sure how to go about this in Redux.
Do you just use the reducer to turn all categories into class instances when you fetch them for example? I'm worried this would be heavy performance wise.
Any write operation to the Firebase Database requires that you know the exact path to the node that you're writing.
There is no built-in operation to bulk update nodes with a path that is only partially known.
You can either keep your client-side code robust enough to handle the missing properties, or you can indeed run a migration script to add the new property to each relevant node. But since that script will have to know the exact path of each node to write, it will likely first have to read/query the database to determine those paths. Depending on the number of items to update, it could possibly use multi-location updates after that to update multiple nodes in one call. E.g.
firebase.database().ref("categories").update({
"idOfMedicalCategory/icon": "newIconForMedical",
"idOfCommercialCategory/icon": "newIconForCommercial"
"idOfTechCategory/icon": "newIconForTech"
})

Meteor drop collection after every query

I am writing an application which communicates with an API and stores the response in a Meteor Collection so I can have the power of mongo to sort/filter.
I would like to clear the collection for every new result set. But a Meteor Collection is persistent.
What is the preferred way of clearing the collection? I know you can drop the meteor collection, but is that the preferred method?
Help appreciated. Thank you!
I would go about creating a local mongo collection which will be available on client side only. To create a client-side collection, just don't give it a name argument.
//This collection is client-only, and will not be sync with server
myCollection = new Mongo.Collection();
//To be more explicit, you can use `null` for the name:
myCollection = new Mongo.Collection(null);
Once you are done using the data empty the collection
myCollection.remove({});
myCollection.remove({}) is the syntax for removing all documents from a collection. This will only work on the server unless the collection is a client-side collection as per #Nakib's example. Otherwise documents can only be deleted by _id on the client side. Normally your allow/deny rules should block any attempt to delete anything on the client as it provides a great attack vector.
Not completely familiar with the Meteor best practice but if you were going to clear out an array in javascript the best practice would be to run the following.
myArrary.length = 0;
For more information I recommend this blog post by David Walsh where he details the reasoning behind zeroing out an array as follows:
Setting the length equal to zero empties the existing array, not
creating another array! This helps you to avoid pointer issues with
arrays as well.

How should I design a multiscreen feature?

I work on a webapp with a workspace, where the user can create, load, and edit documents. This workspace is built with several areas, each taking care of a part of the job. A set of document loaded in a workspace is called a "project" and is stored in a "project" collection.
The data involved in a project is of two types:
the set of documents attached to the project. It is stored in the mongo document in the "project" collection
the current document a specific user is working on. I do not store it yet, I just use a set of global reactive variables to load a document and the attached informations when a user click on it. It means every time a user access to the workspace/project, he will not find the previously loaded documents but no documents loaded at all.
I now want to store the second type of data with one major requirement: to allow the user to work in an "extended mode" where one of the panels is in a dedicated browser window (supposedly on another screen). It means that if he clicks on a document in a window, the document is loaded in the other window/screen.
As far as I know, I can't send information directly from one browser window to another. I have to use the server to relay the information. So the user clicks on a document > the new loaded document id is sent to the server > the other window update accordingly.
Is my assumption correct? (the server must relay the info)
To implement this feature, I figured out a couple of solutions:
I attach a "project" field to the user profile mongo document. In each of these fields, I will have the last items loaded for each project and I will use this field to update one screen from the other.
I create a specific field in each project document where, for each user who worked on the project, I store the currently loaded document and its settings.
The first option suppose to load every project information along with the user profile (i.e. in every page) and could lead to send many times useless informations.
The second option will trigger the meteor reactivity mechanisms each time a user loads an item (without actually modifying the project) for every user connected to the project.
Each option has serious downsides, and I would like to know which one seems to be the better to you and if you can think of other alternatives.
You ought to be able to use one of the reactive local storage packages for Meteor especially if you are not concerned about not supporting non-HTML5 browsers... Can't give a massive amount of guidance on what one having not used most of them but the HTML5 local storage is usable across tabs and seems like a good place to store your data without a round trip to the server whilst also allowing it to persist between tabs.
You could also roll your own implementation (may be simpler than trying to find a package to match your needs exactly) by adding a listener to the app for local storage setitem() and removeItem() events as per this helpful guide from which the below code has been shamelessly copied...
if (window.addEventListener) {
// Normal browsers
window.addEventListener("storage", handler, false);
} else {
// for IE (why make your life more difficult)
window.attachEvent("onstorage", handler);
};
function handler(e) {
console.log('Successfully communicate with other tab');
console.log('Received data: ' + localStorage.getItem('data'));
//Add in your code to display the document on the second tab
}
localStorage.setItem('data', 'hello world');

Anonymous `collection` error in `meteor Js`

I need a help for while creating the collection the below error is came in server console.How to solve the error ?
Error:
Warning: creating anonymous collection. It will not be saved or synchronized over the network. (Pass null for the collection name to turn off this warning.)
TLDR: you need to provide a collection name as an argument when you create a shared collection.
In most cases, you want to provide a name as a parameter when you define a collection:
Docs = new Meteor.Collection('docs');
When you don't, you create anonymous collection:
Items = new Meteor.Collection();
In the first case, the collection is shared and synchronized between client and server, and the name you've provided is used as a table name in order to store the collection in Mongo.
Anonymous collections are local in the place they've been created. Their contents are never synchronized. Therefore, even if you create such collection in a piece of code that will be run on the server and on the client, those two collections will be separate things: data created on the server won't be visible on client, data created on the client won't be visible on server, and both won't be stored in the database.
There are legitimate use cases for anonymous collections, mostly on the client side when you need to create some temporary data, but want to retain all the benefits of Minimongo and reactivity. However, it's one of those things that are needed rarely and you really do know when you need to do it. It's more probable that a beginner made a mistake and forget to provide the collection name when he wanted to create a typical shared collection. Therefore, the system issues a warning to make sure that you really wanted to do what you just did.
Therefore:
If your goal was to create an anonymous collection, and you know what you're doing, don't worry about that message. It's just a warning, the code will be functional and do what it's told to.
If you wanted to create a normal collection, or are just starting out and don't know what's this all about, just add a parameter to your collection definition.

ADO.NET Data Service doesn't Update

I've a problem updating objects with the ADO.NET Data Services.
First I've create a service, which can load and store the data. Its a basic data context which implements the IUpdatable-interface.
After that, I've created a simple service-client. I just created it with the 'Add Service'-reference in Visual Studio. Basically this service seams to work. I can query for the objects and store new objects. However I cannot update objects.
This is my update-code on the client:
var ctx =
new TeamDataContext(new Uri("http://localhost:8637/TeamInfoService.svc"));
var team = ctx.Teams.First();
team.TeamName = "New Team Name";
ctx.UpdateObject(team);
ctx.SaveChanges();
What my main issue is, that IUpdatable.SetValue() isn't called for the object which I want to update. Only the IUpdatable.SaveChanges() is called without updating the objects on the server.
When I create a new object, the IUpdatable.SetValue is called on the server to set the property.
So what I am doing wrong? Are my expectations wrong? Is IUpdatable.SetValue supposed to be called when updating a object? Or do I need to do additional things to do updates?
Edit: I just watched the HTTP-requests between the client and the server. The client send a HTTP-Merge request with the changes. However I still don't know why the changes aren't stored.
I've just found out whats the issue and feel like an idiot right now. The TeamName-property was the Key of the object. Of course, when you change the key, it actually cannot find the object to update anymore. And therefore it cannot update the property.
So, never try to update the key of the object =)

Resources