Create RethinkDB table on first getRecord in deepstream.io - javascript

I have a deepstream server connected to RethinkDB with the official connector.
server.set( 'storage', new RethinkDbConnector({
port: 28015,
host: rethinkDbHost,
splitChar: '/',
defaultTable: 'ds-records'
}));
There are no tables in the database at first.
When I create a record, a table is created automatically if it does not exist.
var id = "chat/" + ds.getUid();
var record = ds.record.getRecord(id);
record.whenReady(function() {
record.set({user: data.user, message: data.message, timestamp: Date.now(), id: id});
});
Table created as intended.
However, if I try to create a "nested table", it does not work.
var id = "chat/idle_banter/" + ds.getUid();
var record = ds.record.getRecord(id);
record.whenReady(function() {
record.set({user: data.user, message: data.message, timestamp: Date.now(), id: id});
});
No table is created when trying to create a record with the name 'table/collection/id'
Do I have to create a table manually first, and then add the collection?
Edit
Clumsy use of terms on my part. I wish to create a table representing the entire chat, and then create a document that represents the actual room. New chat messages (records) would then be put in this document.

I have to admit that I don't think that RethinkDB supports a concept of nested tables. If you'd like to create a table per chat, just use a character other than the splitChar, e.g. 'chat-idle_banter/<recordName>'

Related

get record `id` before create/save | Sails Js

I am trying to create a notification for user.
with notification url in description like this http://localhost:1337/invited/accept?referrer=msgIcon&id=this-notification-id the url has id of this newly created notification.
AppUserNotification.create({
projectId: projectId,
appuser: appusers.id,
notificationTitle: 'You are invited in project',
isRead: 0,
description: 'You are invited in project collaboration, '
+ 'please accept invitation by following the link.\nHave a good day !\n'
+ 'Accept Invitation http://localhost:1337/invited/accept?referrer=msgIcon&id=this-notification-id',
}).exec(function (err, appuserNotifications) {
apiStatus = 1; // heading toward success
if (err){
return false;
}else if(appuserNotifications){
return true;
}
});//</after AppUserNotification.create()>
what I want to do is to save a link in description with this newly created notification. but couldn't manage to do so.
please help me.
By default, id is generated by database during record creating. So can be accessed only after creation.
Here are some ways in which your objective can be achieved:
New attribute: Add another unique attribute which is used in description URL. It can be generated randomly before creation (e.g. can use UUID)
Use custom id: Set autoPK: false in Model, generate id yourself; (I have done it for MySQL in beforeCreate hook using UUID as primary key id, not sure about MongoDB)
Update after create: Use afterCreate hook to update description with id
New Model method: Define a method say getDescription() in the Model which returns something like this.description + this.id.
Override toJSON(): http://sailsjs.com/documentation/reference/waterline-orm/records/to-json

Create a dynamic meteor collection using a variable

I am trying to create a dynamic meteor collection using a variable so a new meteor collection will be created everytime an form is submitted and an event is executed. See code below for what I am looking for though is does not work.
(Keep in mind I am still in the early production stages so I have not set up specific server or client side for debugging purposes. Also, disregard any grammatical or structure errors as i just typed this. just how to make it work)
Intended result:
Suppose user 1 meteor id is x533hf4j3i
Suppose user 2 meteor id is jf83jfu39d
OUTCOME: x533hf4j3ijf83jfu39d = new Mongo.Collection('x533hf4j3ijf83jfu39dmessages')
this sample code that DOES NOT WORK
Template.createChat.events({
'submit form': function(event){
event.preventDefault();
var messageRecipientVar = event.target.messageRecipient.value;
var currentUserId = Meteor.userId();
var recipientUserId = Meteor.users.findOne(messageRecipientVar)._id;
var chatCollectionNameVar = {$concat: [currentUserId, recipientUserId]}
var chatCollectionName = {$concat: [currentUserId, recipientUserId, "messages"]}
chatCollectionNameVar = new Mongo.Collection('chatCollectionName');
}
});
Don't do this. Asking how to create dynamic collections comes up periodically with new meteor developers, but it's never the right approach. #david-wheldon has a great description of why not to do this at the bottom of this page.
Just use one collection Messages, containing documents something like this:
{ _id: xxxxxx,
sender: 'x533hf4j3i',
recipient: 'jf83jfu39d',
message: 'Hi there!',
...
timestamp, etc
...
}
Then it depends on your app if a user can view messages they did not send/receive, and if you need filtering on this you would do it server side in a publish function.
Either way, on the Client if you just want the messages between two users you would query like this:
chatMessages = Messages.find(
{$or: [{ sender: 'x533hf4j3i', recipient: 'jf83jfu39d'},
{ sender: 'jf83jfu39d', recipient: 'x533hf4j3i'}
]}).fetch()

Mongo check if a document already exists

In the MEAN app I'm currently building, the client-side makes a $http POST request to my API with a JSON array of soundcloud track data specific to that user. What I now want to achieve is for those tracks to be saved to my app database under a 'tracks' table. That way I'm then able to load tracks for that user from the database and also have the ability to create unique client URLs (/tracks/:track)
Some example data:
{
artist: "Nicole Moudaber"
artwork: "https://i1.sndcdn.com/artworks-000087731284-gevxfm-large.jpg?e76cf77"
source: "soundcloud"
stream: "https://api.soundcloud.com/tracks/162626499/stream.mp3?client_id=7d7e31b7e9ae5dc73586fcd143574550"
title: "In The MOOD - Episode 14"
}
This data is then passed to the API like so:
app.post('/tracks/add/new', function (req, res) {
var newTrack;
for (var i = 0; i < req.body.length; i++) {
newTrack = new tracksTable({
for_user: req.user._id,
title: req.body[i].title,
artist: req.body[i].artist,
artwork: req.body[i].artwork,
source: req.body[i].source,
stream: req.body[i].stream
});
tracksTable.find({'for_user': req.user._id, stream: req.body[i].stream}, function (err, trackTableData) {
if (err)
console.log('MongoDB Error: ' + err);
// stuck here - read below
});
}
});
The point at which I'm stuck, as marked above is this: I need to check if that track already exists in the database for that user, if it doesn't then save it. Then, once the loop has finished and all tracks have either been saved or ignored, a 200 response needs to be sent back to my client.
I've tried several methods so far and nothing seems to work, I've really hit a wall and so help/advice on this would be greatly appreciated.
Create a compound index and make it unique.
Using the index mentioned above will ensure that there are no documents which have the same for_user and stream.
trackSchema.ensureIndex( {for_user:1, stream:1}, {unique, true} )
Now use the mongoDB batch operation to insert multiple documents.
//docs is the array of tracks you are going to insert.
trackTable.collection.insert(docs, options, function(err,savedDocs){
//savedDocs is the array of docs saved.
//By checking savedDocs you can see how many tracks were actually inserted
})
Make sure to validate your objects as by using .collection we are bypassing mongoose.
Make a unique _id based on user and track. In mongo you can pass in the _id that you want to use.
Example {_id : "NicoleMoudaber InTheMOODEpisode14",
artist: "Nicole Moudaber"
artwork: "https://i1.sndcdn.com/artworks-000087731284-gevxfm-large.jpg?e76cf77"
source: "soundcloud"
stream: "https://api.soundcloud.com/tracks/162626499/stream.mp3? client_id=7d7e31b7e9ae5dc73586fcd143574550"
title: "In The MOOD - Episode 14"}
_id must be unique and won't let you insert another document with the same _id. You could also use this to find the record later db.collection.find({_id : NicoleMoudaber InTheMOODEpisode14})
or you could find all tracks for db.collection.find({_id : /^NicoleMoudaber/}) and it will still use the index.
There is another method to this that I can explain if you dont' like this one.
Both options will work in a sharded environment as well as a single replica set. "Unique" indexes do not work in a sharded environment.
Soundcloud API provides a track id, just use it.
then before inserting datas you make a
tracks.find({id_soundcloud : 25645456}).exec(function(err,track){
if(track.length){ console.log("do nothing")}else {//insert}
});

Mongoose: Adding an element to array

I'm using Drywall to create a website.
I'm trying to add a dashboard element to the accounts section of the admin site. The dashboard element is to store an array of dashboards (strings) that the user has access to.
I've managed to successfully add the "dashboards" into the schema and store data in it.
Here's the problem:
I need to be able to add elements to the array. The way the code stands currently replaces the contents of dashboards in the database.
I know I can use $addToSet, but I'm not sure how I'd do that since the fieldsToSet variable is sent to the findByIdAndUpdate() method as a single object.
Here's the snippet of my code:
workflow.on('patchAccount', function() {
var fieldsToSet = {
name: {
first: req.body.first,
middle: req.body.middle,
last: req.body.last,
full: req.body.first +' '+ req.body.last
},
company: req.body.company,
phone: req.body.phone,
zip: req.body.zip,
search: [
req.body.dashboards,
req.body.first,
req.body.middle,
req.body.last,
req.body.company,
req.body.phone,
req.body.zip,
]
};
req.app.db.models.Account.findByIdAndUpdate(req.params.id, fieldsToSet, function(err, account) {
if (err) {
return workflow.emit('exception', err);
}
workflow.outcome.account = account;
return workflow.emit('response');
});
});
Here's a link to the original file: (lines 184-203)
Thanks!
fieldsToSet is a bad name (at least misleading in this case), the parameter is actually update which can take $actions like $addToSet
I don't think you want to set (only) the search field with dashboards. I'm guessing that field is used to index users for a search. So you'll probably wind up doing something like this:
fieldsToSet = {
....all the regular stuff,
$addToSet: {dashboard: req.body.dashboardToAdd}
//I'm not sure that you can add multiple values at once
}
Since this is setting all of the values each time I'm not sure you actually will want to add single dashboard items. Instead you might want to get the full set of dashboards the user has and set the whole array again anyway (what if they removed one?)
fieldsToSet = {
....all the regular stuff,
dashboards: req.body.dashboards
//In this case you'd want to make sure dashboards is an appropriate array
}

Saving node.js post data to show all records that have been added since the web application was started

I'm working on a web application using node.js that has a form containing basic information about a person. I need to have all records that have been added since the web application was started display on the submit page.
I believe that I need to create an array to store this information but this is where my confusion starts. I'm not sure where to create the array to add information to. I suspect it should be in app.js where I call app.post('/add', routes.add);
I think it should maybe something like this going from an example I found here How do I add a new complex entry to a javascript array?:
// Routes
app.get('/', routes.index);
app.post('/add', routes.add);
var people = [{name, country, date, email, phone}];
people.push({name, country, date, email phone});
However the array looks like it will only hold enough information for 1 person.
Please let me know if my question is not clear enough and I will try to clarify
Thanks in advance!
Edit: I believe that when I am calling routes.add this code is executed from my index.js file
exports.add = function(req, res){
res.render('add', { title: 'Person added',
name: req.body.name,
country: req.body.country,
date: req.body.birthday,
email: req.body.email,
phone: req.body.phone});
};
and in my add.jade file:
h1 Info Added
p Name: #{name}
p Country: #{country}
p Date: #{date}
p Email: #{email}
p Phone: #{phone}
There are a few things to maybe get you started.
Database
I suggest you move the database to another file, that way you may replace it with a 'real' database later. Ie. do something like this:
create a lib directory in app root,
create a db.js in that directory,
put this code in the db.js:
var database = [],
counter = 0;
// add method adds a new object to db.
exports.add = function(person) {
person.id = counter;
counter = counter + 1;
database.push(person);
return id; // we return id, so that we can use it as a reference to this object.
}
// get method retreives the object by id.
exports.get = function(id) {
return database[id]; // this will return undefined if there is no such id
};
exports.list = function(){
return database;
}
Now you have a database.
Controllers
You use the db in other files like this:
var people = require('lib/db');
// or if you're in a routes directory,require('../lib/db') or appropriate path
people.add({name: 'Sarah'}); // returns 0
people.add({name: 'Zlatko'}); // returns 1
people.get(1); // returns {name: 'Zlatko'}
Now in your routes/index.js you can include your database and have this to save or retreive an user or all users. Somehing similar to your exports.add:
var id = people.add({name: req.body.name, email: req.body.email});
res.render('add', people.get(id));
You can also create a 'people' view and just pass it {people: people.list()} object as parameters array.
I didn't include any validation, checking, anything ,to make the example more clear. This db can hold more then one person, and it's enough to get you started. And I think it is clear in what it does.
I hope this helps.

Categories

Resources