In creating a primary key in a Forerunner database collection, can the key property live inside of an object of the collection object? - javascript

I have a work-around, however I'm wondering why this is failing - is it a JavaScript error on my part?
My app uses two models. I'm using Forerunner to persist a JSON model that is previously created in my MVC.
I want to store the Forerunner primary key in an object, to make it clearer (in my first model) that the key is used only in the Forerunner model.
The key will need to be saved in both models, so that when the first model changes, I can immediately update the Forerunner model - it is the link between two models.
Here is a code sample to illustrate:
var games = db.collection("games", {
primaryKey: "gamedb._id"
});
games.insert({
gamedb : {
_id: 1,
},
userDesc : "original 11x11",
Size : [11,11],
Plays : []
.
.
}, function (result) {
console.log(result);
});
I did try it out, and got confusing results, so for now I'm just leaving the key as property of the collection.
Here is the console.log result of my attempt using the above code sample. The forerunner insert() did not fail.
I'm confused about the property 'gamedb._id : "225b...".
Thanks for any suggestions or insight.
gamedb : Object
_id: 1
gamedb._id: "225b3c25aeb38a0",
}
.
.

Primary keys in ForerunnerDB must currently be in the root of the object. When you tell it to make the primary key "gamedb._id" it is not parsing that string as a path, it is assuming you are passing that as a root key e.g. {"gamedb._id": myId}
There are plans to update ForerunnerDB to allow nested primary keys, but this is not currently possible.
Source: I wrote ForerunnerDB

Related

couchdb views: return all fields in doc as map

I have a doc in couchDB:
{
"id":"avc",
"type":"Property",
"username":"user1",
"password":"password1",
"server":"localhost"
}
I want to write a view that returns a map of all these fields.
The map should look like this: [{"username","user1"},{"password","password1"},{"server","localhost"}]
Here's pseudocode of what I want -
HashMap<String,String> getProperties()
{
HashMap<String,String> propMap;
if (doc.type == 'Property')
{
//read all fields in doc one by one
//get value and add field/value to the map
}
return propMap;
}
I am not sure how to do the portion that I have commented above. Please help.
Note: right now, I want to add username, password and server fields and their values in the map. However, I might keep adding more later on. I want to make sure what I do is extensible.
I considered writing a separate view function for each field. Ex: emit("username",doc.username).
But this may not be the best way to do this. Also needs updates every time I add a new field.
First of all, you have to know:
In CouchDB, you'll index documents inside a view with a key-value pair. So if you index the property username and server, you'll have the following view:
[
{"key": "user1", "value": null},
{"key": "localhost", "value": null}
]
Whenever you edit a view, it invalidates the index so Couch has to rebuild the index. If you were to add new fields to that view, that's something you have to take into account.
If you want to query multiple fields in the same query, all those fields must be in the same view. If it's not a requirement, then you could easily build an index for every field you want.
If you want to index multiple fields in the same view, you could do something like this:
// We define a map function as a function which take a single parameter: The document to index.
(doc) => {
// We iterate over a list of fields to index
["username", "password", "server"].forEach((key, value) => {
// If the document has the field to index, we index it.
if (doc.hasOwnProperty(key)) {
// map(key,value) is the function you call to index your document.
// You don't need to pass a value as you'll be able to get the macthing document by using include_docs=true
map(doc[key], null);
}
});
};
Also, note that Apache Lucene allows to make full-text search and might fit better your needs.

Update Array from Document (MongoDB) in Javascript not Working

I've looking for an answer for like 5 five hours straight, hope somebody can help. I have a MongoDb collection results (I'm using mLab) which looks like this:
{
"user":"5818be9c74aaec1824c28626"
"results":[{
"game_id":14578,
"level1":-1,
"level2":-1,
"level3":-1
},
{ ....
}],
{ "user":....
}
}
"user" is a MongoID I save in a previous part of the code, "results" is a record of scores. When an user does a new score, I have to update the score of the corresponding level (I'm using NodeJS).
This is one of the things I've tried so far.
app.get('/levelCompleted/:id/:time', function (request, response) {
var id = request.params.id;
var time = parseInt(request.params.time);
var u= game.getUserById(id);
var k = "results.$.level"+(u.level);
//I build the key to update dinamycally
dbM.collection("results").update(
{user:id,
"results.game_id":u.game_id
//u has its own game_id
},
{$set: {k:time}}
);
...
response.send(...);
});
I've checked the content of every variable and parameter, tried also using $elemMatch and dot notation, set upsert and multi, with no results. I've used an identical command on mongo shell and it has work on the first try.
Update with Mongo Shell
If someone could tell me what I'm doing wrong or point me in the right direction, it would be great.
Thanks
When you use a MongoId as a field in a MongoDB, you can't just pass a string with the id to do the query, you have to identify that string as an ObjectId (Id type in Mongo). Just add a new require in your node.js file.
var ObjectID = require("mongodb").ObjectID;
And use the imported constructor in your update request.
dbM.collection("results").update(
{user:ObjectID(id),...
...
}

I'm getting a "newItem() was not passed an identity for the new item" error while trying to add a new item to a JSON store

I've seen other posts in this site regarding the same issue and I've tried the solutions given. I've also visited the links that may offer a solution but I'm still stuck with the same error.
I'm using DOJO and something as simple as this won't even work
myStore.newItem({id: 'test', otherfield: 'otherinfohere'});
myStore.save();
Supposedly the "newItem() was not passed an identity for the new item" error appears when you haven't provided an identifier for the new item, which i have.
The whole purpose of this (Just in case anyone can provide a good idea or has done something similar before) is that i want to create a data grid that shows info from a particular store. The problem is, that in that store all the items may not have the same structure. For instance:
I may have a store that looks like this
{identifier: 'id',
label: 'name',
items: [
{ id:'1', name:'Ecuador', capital:'Quito' },
{ id:'2', name:'Egypt', capital:'Cairo' },
{ id:'3', name:'El Salvador', capital:'San Salvador' , additionalField: 'otherinfohere'},
{ abbr:'gq', name:'Equatorial Guinea', capital:'Malabo', additionalField: 'otherinfohere'},
]}
This is possible because I'm the one constructing the store in a Spring Controller (I'm also using the Spring Framework) from information I have locally stored in a Berkeley DB. So what i need is a data grid with a dynamic layout because I don't want blank spaces to show in the view in the rows with lesser amount of fields, and i need to show all the info in the store at the same time, but i don't know how to do this.
I thought of doing it by creating a simple layout of only 1 field. In it I would load data from a store i create dynamically at runtime. The data in the store would be composed of HTML combined with the values coming from the original store so I could obtain something like this, which is inside an attribute of a JavaScript Object and let the browser parse it for me:
<div><span>id: originalID </span>....</div>
This of course is a simple example, the html layout i'm looking for is far more complicated, but i think that passing it as a string to an object might do the trick.
The problem is that i don't even know if that idea will work because i get that error whenever i try to add values to my secondary store.
rdb.modules.monitor.historicStore.fetch({onComplete: function(items, request){
for (var i = 0; i < items.length; i++){
var item = items[i];
var obj = new Object();
obj.id = rdb.modules.monitor.historicStore.getValue(item, "id");;
var html = "<div><span>";
html += rdb.modules.monitor.historicStore.getValue(item, "sql");
html += "</span></div>";
obj.html = html;
myStore.store.newItem(obj);
}
}});
In this context "historicStore" refers to the JSON store that has the values that i need to convert and add to "myStore" after i added some HTML.
I hope you got the main idea of what I'm trying to do. If anyone can help me we either of these problems i would really appreciate it. Thanks in advance
For the issue regarding store:-
"id" is mandatory for a store, if it is going to be used for a grid(datagrid, EnhancedGrid, etc. whatever). The items are handled only on basis of "id" attribute by the grid data structures.
Usually, id can be a loop variable/ auto incrementation, to avoid any cases like you have said. Before adding the store to the grid, ensure that all items have the id attribute. You can write a function which will loop through each item and check for this, else add an auto-incrementing value for the id attribute of that item.

Backbone-relational: Association key won't work unless it's the same as the foreign key

I'm trying to get the backbone-relational plugin working with an association between tasks and messages. (A task has many messages).
The information is pulled from a standard rails/activerecord site, which has a task_id field as the foreign key.
The problem is, backbone-relational won't populate the 'messages' field with any messages on teh Task model unless I set the key as "task_id" in the reverse relation...but that means that, when accessing the task from the Message model, the task_id field is populated with the actual task object, not the 'task_id' integer, which is overwritten.
I'm guessing there's a simple way to specify task_id as the foreign key with which to determine the parent task, yet have the object that key represents placed in a different field (eg 'task' on the messages object)...but I can't figure out how. Any ideas appreciated. Code below
class Backbonescaffolddemo.Models.Task extends Backbone.RelationalModel
paramRoot: 'task'
relations: [{
type: Backbone.HasMany,
key: "messages",
relatedModel: "Backbonescaffolddemo.Models.Message",
collectionType: "Backbonescaffolddemo.Collections.MessagesCollection",
includeInJSON: true
reverseRelation: {
key: "task_id"
includeInJSON: true
}
}]
You may be able to use keySource or keyDestination to address your particular problem.
Example
In the following example, suppose we are getting data from an old-school relational database, where there is a one-to-many relationship between Monster and Loot_Item. This relationship is expressed by a Monster_Id foreign key in the Loot_Item table. Let us also suppose that our REST service doesn't do any fancy-pants data nesting for us, since that seems to match the situation in your question fairly closely.
keySource
Now, let's set set "keySource" to my foreign key ("Monster_Id") and "key" to the name of the attribute where I want the actual data to go (say, "Monster"). If you break in the debugger, you will see in the attributes object that there is, in fact, a field called "Monster", and that it does point to the monster model data. Hey, cool!
includeInJSON
However, if you toJSON that puppy, guess what? It has put all the monster data in Monster_Id, just like you didn't want! GAH! We can fix that by setting "includeInJSON" to "Monster_Id". Now, when it is converted to JSON, it puts the proper ID back into the Monster_Id field, when it is serializing your data to JSON, to send up to the server.
Problem solved? Er, well, actually, not necessarily...
CAVEAT: This all sounds super-useful, but there's one fairly glaring problem that I have found with this scenario. If you are using a templating engine (such as the one in Underscore.js) that requires you to convert your model to JSON, before passing it into the template, whoops -- you don't have access to your relational data. Alas, the JSON that we want for our messages is not necessarily the same JSON that we want to feed into our templates.
If you want the "task_id" in the message JSON to be the id, not the full JSON for the task, then set the "includeInJSON" to be the Task's ID property ("task_id")
class Backbonescaffolddemo.Models.Task extends Backbone.RelationalModel
paramRoot: 'task'
relations: [{
type: Backbone.HasMany,
key: "messages",
relatedModel: "Backbonescaffolddemo.Models.Message",
collectionType: "Backbonescaffolddemo.Collections.MessagesCollection",
includeInJSON: true
reverseRelation: {
key: "task_id"
includeInJSON: "task_id"
}
}]
The "true" value for includeInJSON says to use the full JSON for the related model.
Edit: After re-reading your question, I'm not sure my answer relates to your issue.
My original answer is for posting a message back to the server where you want the JSON to be something like:
{
"message_title": "My Title",
"message_body": "Blah blah blah...",
"task_id": 12345
}
I'm not sure what exactly you're looking to happen, but the way that Backbone Relational is supposed to work is that the Task's collection of messages will be a collection of the full models, so you can iterate over them and pass them to views for rendering, etc.
If you want to output one of the Message's id's in a template or something, then you'd take the Message model's "id":
myTask.get('messages').first().id -> returns the first message's id

How do I get a model from a Backbone.js collection by its id?

In my app, everything I do with data is based on the primary key as the data is stored in the database. I would like to grab a model from a collection based on this key.
Using Collection.at() requires the array index, Collection.getByCid() requires the client ID that backbone randomly generates.
What is the best way to grab the model I want from the collection with the given id value? I figure the worst I could do would be to iterate over each item, .get('id'), and return that one.
Take a look at the get method, it may be of some help :)
http://backbonejs.org/#Collection-get
get collection.get(id)
Get a model from a collection, specified by an id, a cid, or by passing in a model.
If your data requires you to use a different kind of key or a set that doesn't mesh well with at(), getByCid() or get(), there is also where(). Something like this might work:
window.lib = new Library;
window.lib.fetch([
success: function(model, response) {
console.log(window.lib.where({'BookID':488, 'Rev':2, 'Status':'Active'});
}
});

Categories

Resources