Nested models in Backbone - backbone.js

I am new to Backbone and I have an issue regarding nested models. Here I have data.json where I have following JSON:
[
{
"name": "Project",
"description" : "This is a Peugeot website",
"url" : "http://peugeot.am",
"images" : [
{ "image" : "A", "thumb" : "a" },
{ "image" : "B", "thumb" : "b" },
{ "image" : "C", "thumb" : "c" }
]
},
{
"name" : "Ararat",
"description" : "This is a Ararat website",
"url" : "http://ararat.am",
"images" : [
{ "image" : "A", "thumb" : "a" },
{ "image" : "B", "thumb" : "b" },
{ "image" : "C", "thumb" : "c" }
]
},
{
"name" : "Procredit Bank",
"description" : "This is a Procredit Bank website",
"url" : "http://procredit.am",
"images" : [
{ "image" : "A", "thumb" : "a" },
{ "image" : "B", "thumb" : "b" },
{ "image" : "C", "thumb" : "c" }
]
}
]
In Backbone I am trying to fetch data, but I get empty array.
var myapp = myapp || {};
$(function () {
myapp.Image= Backbone.Model.extend({
initialize: function () {
this.Img = this.get('image');
this.Thumb = this.get('thumb');
}
});
myapp.Images= Backbone.Collection.extend({ model: myapp.Image });
myapp.Item= Backbone.Model.extend({
initialize: function () {
this.Name = this.get('name');
this.Description = this.get('description');
this.URL = this.get('url');
this.subs = new myapp.Images(this.get('images'));
}
});
myapp.Items= Backbone.Collection.extend({
model: myapp.Item,
url: 'content/js/data.json',
parse: function (resp, xhr) { return JSON.parse(resp); }
});
var items = new myapp.Items();
items.fetch();
console.log(items.toJSON());
});
Now, what am I doing wrong above? I need to fetch data to get JSON so to start manipulate with it.
Thanks in advance!

the default support is pretty lacking you would need to get the data for each nested model separately
There are library such as
https://github.com/powmedia/backbone-deep-model
and
http://afeld.github.io/backbone-nested/
Which can be used instead

items.fetch();
console.log(items.toJSON());
Collection.fetch() is an asynchronous operation. It won't produce a response until the request gets back from the server. Try this:
items.fetch().done(function(){
console.log(items.toJSON());
});
You can also use the web inspector in safari/chrome (or firefox debugger / firebug) to monitor network requests and see that your calls are firing successfully (and inspect the responses), or put another console.log statement inside the 'parse' function of your collection.
http://backbonejs.org/#Collection-fetch

Related

Update documents nested multiple levels in an array

I have this JSON structure in MongoDb and want to update changing a specific value of a particular item in a nested array. I would like to change the key targetAreaId from USER_MESSAGE to VISUAL_MESSAGE.
{
"_id" : "5cde9f482f2d5b924f492da2",
"scenario" : "SCENARIOX",
"mediaType" : "VISUAL",
"opCon" : "NORMAL",
"stepConfigs" : [
{
"stepType" : "STEPX",
"enabled" : true,
"configs" : [
{
"contentTemplateId" : "5cde9f472f2d5b924f492973",
"scope" : "STANDARD",
"key" : "CONTENT"
},
{
"priorityId" : "5cde9f472f2d5b924f49224f",
"scope" : "STANDARD",
"key" : "PRIORITY"
},
{
"targetAreaId" : "USER_MESSAGE",
"scope" : "STANDARD",
"key" : "TARGET_AREA"
}
],
"description" : "XPTO"
}
],
"scope" : "STANDARD" }
How can I do it in the same time?
EDIT
I am trying this way:
var cursor = db.getCollection('CollectionX').find({
"scenario": "SCENARIOX",
"stepConfigs.stepType": "STEPX",
"stepConfigs.configs.key": "TARGET_AREA"
});
if (cursor.hasNext()) {
var doc = cursor.next();
doc.stepConfigs.find(function(v,i) {
if (v.stepType == "STEPX") {
doc.stepConfigs[i].configs.find(function(w,j) {
if (w.key == "TARGET_AREA") {
var result = db.getCollection('CollectionX').update(
{ "_id" : doc._id },
{ "$set" : { doc.stepConfigs[i].configs[j].targetAreaId: "VISUAL_MESSAGE" }}
);
}
});
};
});
} else {
print("Step does not exist");
}
But the error below is occurring:
Error: Line 15: Unexpected token .
I don't think that's possible.
You can update the specific element you want using this query:
db.test_array.updateOne({}, {
$set: {
"stepConfigs.$[firstArray].configs.$[secondArray].targetAreaId": "VISUAL_MESSAGE"
}
}, {
arrayFilters: [{
"firstArray.stepType": "STEPX"
}, {
"secondArray.targetAreaId": "USER_MESSAGE"
}]
})
But pushing in the same array at the same time does render this (this was for the original model, but it's still the same problem, you can't $set and $push in the same array this way):
> db.test_array.updateOne({"step.type":"B"},{$push:{"step.$.configs":{"className":"something"}}, $set:{"step.$.configs.$[secondArray].targetAreaId":"TA-1"}},{arrayFilters:[{"secondArray.targetAreaId":"TA-2"}]})
2019-09-06T13:53:44.783+0200 E QUERY [js] WriteError: Updating the path 'step.$.configs.$[secondArray].targetAreaId' would create a conflict at 'step.$.configs' :

Sort in mongoDB using a specific order

I am currently looking to sort the sub document, Clients, in a particular order based on an array.
The mongoDB structure is
{
"_id" : "1033",
"Name" : "Test",
"Clients" : [
{
"Id" : 1033,
"Types" : [
{
"Class" : "C",
"Service" : null
},
{
"Class" : "B",
"Service" : null
}
]
},
{
"Id" : 156136,
"Types" : [
{
"Class" : "A",
"Service" : null
},
{
"Class" : "B",
"Service" : null
},
{
"Class" : "C",
"Service" : null
},
{
"Class" : "D",
"Service" : null
}
]
}
]
}
I need the above document displayed in the order based on a array like [B, A, D, C]
So that the output would be as below:
{
"_id" : "1033",
"Name" : "Test",
"Clients" : [
{
"Id" : 1033,
"Types" : [
{
"Class" : "B",
"Service" : null
},
{
"Class" : "C",
"Service" : null
}
]
},
{
"Id" : 156136,
"Types" : [
{
"Class" : "B",
"Service" : null
},
{
"Class" : "A",
"Service" : null
},
{
"Class" : "D",
"Service" : null
},
{
"Class" : "C",
"Service" : null
}
]
}
]
}
Could you please help me on how to achieve this?
I am currently using MongoDB Driver for .Net
Custom ordering is possible via aggregation as specified here.
I've solved my problem with custom sorting , using $addFields and $indexOfArray aggregations.
let imagine that my document has two fields: BouqetId, Name
[
{ "BouqetId" : 2, "Name" : "Name2"},
{ "BouqetId" : 16, "Name" : "Name16"},
{ "BouqetId" : 25, "Name" : "Name25"},
{ "BouqetId" : 15, "Name" : "Name15"},
{ "BouqetId" : 125, "Name" : "Name125"},
{ "BouqetId" : 258, "Name" : "Name258"},
{ "BouqetId" : 127, "Name" : "Name127"}
...
]
and I want to search for Bouqet with Ids [258,15,2,16] and get them with this order.
1/ I filter my collection using $in operator in $match aggregation to get the required documents: view step one in code.
2/ I add a field using $addFields aggregation named Order and assign to it the index of the BouqetId in the searched array using $indexOfArray aggregation.
3/ finally I sort them using the newly added Order field.
4/ I get my custom-ordered result. I can remove the order field but it is ok for now.
here and exmaple in Nodejs :
var db = client.db("MyDatabase");
var collection = db.collection("Bouqets");
var pipeline = [
{
"$match": {
"BouqetId": {
"$in": [
258,
15,
2,
16
]
}
}
},
{
"$addFields": {
"Order": {
"$indexOfArray": [
[
258,
15,
2,
16
],
"$BouqetId"
]
}
}
},
{
"$sort": {
"Order": 1.0
}
}
];
var cursor = collection.aggregate(pipeline);
Here my result :
[
{ "BouqetId" : 258, "Name" : "Name258" , "Order" : 0},
{ "BouqetId" : 15, "Name" : "Name15", "Order" : 1},
{ "BouqetId" : 2, "Name" : "Name2", "Order" : 2},
{ "BouqetId" : 16, "Name" : "Name16", "Order" : 3}
]
here the same example in c# :
IMongoClient client = new MongoClient("mongodb://host:port/");
IMongoDatabase database = client.GetDatabase("MyDatabase");
IMongoCollection<BsonDocument> collection = database.GetCollection<BsonDocument>("Bouqets");
var options = new AggregateOptions()
{
AllowDiskUse = false
};
// my array
var searchArray = new int[] {258, 15, 2, 16};
PipelineDefinition<BsonDocument, BsonDocument> pipeline = new BsonDocument[]
{
new BsonDocument("$match", new BsonDocument()
.Add("BouqetId", new BsonDocument()
.Add("$in", new BsonArray(searchArray)
)
)),
new BsonDocument("$addFields", new BsonDocument()
.Add("Order", new BsonDocument()
.Add("$indexOfArray", new BsonArray()
.Add(new BsonArray(searchArray)
)
.Add("$BouqetId")
)
)),
new BsonDocument("$sort", new BsonDocument()
.Add("Order", 1.0))
};
var result = collection.Aggregate(pipeline, options).ToList();
Custom ordering is not possible in MongoDB. You can either sort ascending or descending.

mongoDB - How to update/insert a field in an object which is within an array?

I have a method which inserts a new document into the collection "items".
//Example data of variables
var home = "home1";
var itemId = "123";
var username = Meteor.user().username;
//Upsert command
items.upsert({
'_id': home
}, {
$push: {
'createdItems': {itemId, username, home}
}
});
This creates a document like this:
"_id" : "home1",
"createdItems" : [
{
"itemId" : "123",
"username" : "Jon Doe",
"home" : "home1"
},
{
"itemId" : "456",
"username" : "Jon Doe2",
"home" : "home1"
},
{
"itemId" : "789",
"username" : "Jon Doe3",
"home" : "home1"
}
]
}
Now I need to be able to update the existing fields and insert new fields into these objects later. The itemId within these objects is the "reference". So I need a mongoDB function which inserts or updates fields by using the "itemId" as a query operator. Something like this:
//update a field
items.upsert({
'itemId': "123"
}, {
$set: {
'createdItems': {username: "Clark Kent"}
}
});
//insert new field
items.upsert({
'itemId': "123"
}, {
$set: {
'createdItems': {Value: 1000}
}
});
Or do I have to use $push? These commands are not delivering the results that I need. At the end the document should look like this:
"_id" : "home1",
"createdItems" : [
{
"itemId" : "123",
"username" : "Clark Kent",
"home" : "home1",
"Value" : 1000
},
{
"itemId" : "456",
"username" : "Jon Doe2",
"home" : "home1"
},
{
"itemId" : "789",
"username" : "Jon Doe3",
"home" : "home1"
}
]
}
Or do I have to use another data schema for the collection? If yes, which one can I choose when I want to have "itemId, "username" and "home" still in an array but "packed together"?
Many thanks.
If you want to update object in array query below will work fine
items.update({
'createdItems.itemId': '123'
}, {
$set: {
'createdItems.$.username': 'Clark Kent'
}
})
You can also easily add new fields to the object using the same query.
items.update({
'createdItems.itemId': '123'
}, {
$set: {
'createdItems.$.username': 'Clark Kent'
'createdItems.$.newField': 'newFieldValue'
}
})

Array filter in angularjs

I need to make a filter that searches the following array of objects and filters out those objects whose ID value is equal to a Message value in any of those objects in the array. Also the filter should return only objects with level equal to 1. I've already managed to filter the level property, but I can't seem to figure out how to do the rest.
Let's consider an example: ID: 001 contains in its Message 006, so I want to filter out all objects, whose ID is 006.
$scope.myData = [
{
"ID" : "001",
"Message" : "006",
"level":"1"
},
{
"ID" : "002",
"Message" : "test test test test1",
"level":"1"
},
{
"ID" : "003",
"Message" : "test test test test",
"level":"1"
},
{
"ID" : "004",
"Message" : "test test test test",
"level":"1"
},
{
"ID" : "005",
"Message" : " My Test",
"level":"1"
},
{
"ID" : "006",
"Message" : "",
"level":"1"
},
{
"ID" : "007",
"Message" : "next level",
"level":"2"
}
];
})
And filter:
app.filter('filterData3', function () {
return function (data) {
var dataToBePushed = [];
data.forEach(function (resultData) {
if (resultData.level == 1)
dataToBePushed.push(resultData);
});
return dataToBePushed;
}
});
Assuming that what you want is to NOT include in your filtered array the elements which ID is contained in another element's Message, you could write a filter like the following:
.filter('filterData3', function () {
return function (data) {
var dataToBePushed = [];
var messages =[];
data.forEach(function (resultData) {
if (resultData.level == 1 && (messages.indexOf(resultData.ID) == -1)) {
messages.push(resultData.Message);
dataToBePushed.push(resultData);
}
});
return dataToBePushed;
}})
Hope this works for you

How to query the firebase database to fetch specific data?

{
"todo" : {
"Kujbghnkj04t56-" : {
"id" : 1,
"tags" : [ {
"name" : "Italy"
}, {
"name" : "Australia"
} ],
"username" : "ABC"
},
"oPikoieew9oR-" : {
"id" : 2,
"tags" : [ {
"name" : "Switzerland"
} ],
"username" : "XYZ"
}
}
}
I am trying to search in Firebase according to tags name. My code is:
var tagRef = new Firebase(FURL+'/todo');
var tagCollection = $firebaseArray(tagRef);
tagCollection.$ref().orderByChild("tags").equalTo("Australia").once("value", function(dataSnapshot){
// code
});`
How can I get the snapshot of all data containing tag name as "Australia"

Resources