How to search by object with nested object in AngularJS - javascript

I want to filter my orders collection by search object. want to show only matching order in view.
I have orders array collection like:
$scope.orders = [{
"_id" : "56461e2b7caaf49345076709",
"customer" : {"_id": "76461e2b7caaf49345076a19b", "name": "cr1"},
"seller" : {"_id": "96461e2b7caaf49345076a18b", "name": "sl1"},
"address" : "Squire Park",
"qt" : 5
},
{
"_id" : "56461e2b7caaf49345076708",
"customer" : {"_id": "76461e2b7caaf49345076a19b1", "name": "cr2"},
"seller" : {"_id": "96461e2b7caaf49345076a18c1", "name": "sl2"},
"address" : "Squire Park1",
"qt" : 6
},
..................
];
and my search object like:
$scope.search = {
"qt": 5,
"customer" : {"_id": "76461e2b7caaf49345076a19b1"},
"seller" : {"_id": "96461e2b7caaf49345076a18c1"}
};
view:
<tr data-ng-repeat="order in orders | myFilter:search">
<td>{{order._id}}</td>
<td>{{order.customer.name}}</td>
</tr>
What should be my myFilter function?
Thanks advance.

A rather simple solution would be attaching a filter function to the scope
$scope.orderFilter = function(order) {
// implementation depends on how you want the search to behave
// for example, if the order should match every property of the searchObj
var pass = true;
for (var property in $scope.search) {
if ($scope.search.hasOwnProperty(property)) {
if($scope.search[property] != order[property]) {
pass = false;
}
}
}
return pass;
// .. though i wouldnt recommend this implementation
// you´d be better off by implementing a more specific matching
}
And in the view
<tr data-ng-repeat="order in orders | filter:orderFilter">
<td>{{order._id}}</td>
<td>{{order.customer.name}}</td>
</tr>
If you want the filter-expression you are using to work, you have to register a custom filter on your module. This would be done like so:
angular.module('app').filter('myFilter', function() {
return function(orders, searchObj) {
var filteredOrders = [];
orders.forEach(function(order) {
// evaluate if you want to have the order show up based on the searchOjb
// .. if so, add it to the array like so:
filteredOrders.push(order);
});
return filteredOrders;
}
});
NOTE
If you change a property of you search object, your filter function wont be called again, because angular filters arent listening for changes of nested properties. The filter will only be called if you change the whole search object.

Related

MongoDB- Return Array of existing fields by compare collection with Array of object

I'm new to Mongo and trying compare a array with a documents of collections and return list of matching records.
Let me explain:First Array
I have a collection (user) with following documents:
> db.user.find().pretty()
{
"_id" : ObjectId("57358220bf3e7d076b6ccdb1"),
"name" : "Sunny",
"phone" : "9417702107",
"email" : "ssdhiman07#gmail.com"
}
{
"_id" : ObjectId("57358242bf3e7d076b6ccdb2"),
"name" : "Pal",
"phone" : "9015719419",
"email" : "ss998#gmail.com"
}
{
"_id" : ObjectId("57358262bf3e7d076b6ccdb3"),
"name" : "viveky",
"phone" : "8826565107",
"email" : "sds998#gmail.com"
}
Second Array: i have a array of objects that is come from Http request below is structure of array.
{
"contacts" : [
{
"name" : "Sunny",
"phone" : "9417702107"
},
{
"name" : "Sukhpal",
"phone" : "9015719419"
},
{
"name" : "anurag",
"phone" : "9988776655"
},
{
"name" : "vivek",
"phone" : "8826565107"
}
]
}
Now I want to know which objects of Second Array are exists in First Array and which doesn't . Comparison should on basis of phone only . And in result i want same Array as Second Array but with one extra field that is
"exists":"true" or "exists":"false" . Something like this.
{
"contacts" : [
{
"name" : "Sunny",
"phone" : "9417702107"
"exists" :"true"
},
{
"name" : "pal",
"phone" : "90177668899"
"exists" :"false"
}
]
}
So for this i had tried something here is code of node.js with mongoos.
exports.matchcontacts = function(req, res, next)
{
var response = {};
var conArray = req.body.contacts;
var contact_list = [];
for(var i=0; i<conArray.length;i++)
{
var name = conArray[i].name;
var phone = conArray[i].phone;
Users.findOne({"phone":conArray[i].phone},function(err,data)
{
if(err)
{
response = {"error" : true,"message" : "Error fetching data"};
}
else if(!data)
{
contact_list.push({name:name,phone:phone,exists:"false"});
}
else
{
contact_list.push({name:name,phone:phone,exists:"true"});
}
});
}
response = {"error":false,"contacts":contact_list};
res.json(response);
};
But always got null {} empty result, and if i tried to get response inside Callback function then it return only single last compared value.
Problem is in first method is that callback function return result very late so result always empty .
and in second method loop override result and it also inefficient to use callback inside loop it will call no of time. So whole story i had explained
Now Please can anybody help me with code or suggest right way to get desired result thanks
Haven´t used mongodb, but the idea I would use is to first iterate your contacts and make a mapping of the phones to the corresponding object and mark them as non existent:
var obj = {};
for(var i=0; i<conArray.length;i++){
obj[conArray[i].phone] = conArray[i];
conArray[i].exists = false;
}
Then search in some way for the users that have those phones in your db, something like
var results = Users.find(records that have phone in Object.keys(obj) array)
Finally, you iterate your existant records and mark the corresponding contact
for(var i=0;i<results.length;i++){
obj[results[i].phone].exists = true;
}

mongoDB: Find missing documents in model tree structure with parent reference

I have some documents which are organized in a model tree structure (depth is variable!). Unfortunately some documents are missing and I need to find those broken chains. As you can see the last document in that chain has always the target field. This is the starting point and I have to look upwards using parent. The last element in that chain has always the field type.
{
"_id" : "K7NSxNEnNSr9nCszR",
"title" : "title",
"type" : "book",
"ancestors" : [ ]
}
{
"_id" : "diyvwYz66yoTCTt9L",
"field" : "something",
"parent" : "K7NSxNEnNSr9nCszR",
"ancestors" : [
"K7NSxNEnNSr9nCszR"
]
}
{
"_id" : "diyvwYz66yoTCTt9L",
"field" : "anything",
"target" : "D2YuXtM6Gzt4eWaW2",
"parent" : "QWvdAyftSGANM3zy8",
"ancestors" : [
"K7NSxNEnNSr9nCszR",
"QWvdAyftSGANM3zy8"
]
}
What I need to know is if any parent is missing or if the last element (=type existing) is missing.
var broken = [];
Collection.find({ target: { $exists: true }}).forEach(function(element) {
var startDocID = element._id;
if (Collection.find({ _id: element.parent }).count() === 0)
broken.push(startDocID);
});
console.log(broken);
But this isn't working well as I need to use a loop to get upwards until the top document (= type existing).
You're talking about recursion here if you need to go down the tree, so you probably need to write a recursive search function
var broken = [];
Collection.find({ target: { $exists: true }}).forEach(function(element) {
function recurse(e) {
var startDocID = e._id;
var nodes = Collection.find({ _id: e.parent });
if (node.count() === 0)
{broken.push(startDocID);}
else {
nodes.fetch().forEach(node) {
recurse(node)
}
}
recurse(element);
}
});
or something of that sort... (hard to debug without the data)

Create a JSON object with variables as fields

I want to create a JSON object with variables as associative variable names similar to the following:
var field = 'first';
var query = { details.field, details.field };
I would prefer if the details were a fixed value.
This is my dataset currently
{
field1: ,
group: {
first:
}
}
My question is, how would I go about creating JSON objects with variables as fields?
You can add a property to an object like so:
var query = { details: {} };
var field = 'first';
query.details[field] = "TEST";
Which will give you the object:
{ details: { first: "TEST" }}
which you can then access with query.details.first or query.details[field];
Is that what you're looking for?
A simple way to accomplish this in Javascript is using the . operator.
query.details.field = "first";
This will product an object as follows:
"query" { "details" { "field": "first"} }
Is this what your looking for?
If you want multiple details you will want to use an array.
var query = [];
query.push({"details" { "field" : "first"} });
query.push({"details" { "field" : "second"} });
This will product an object like this
"query" [
"details" { "field" : "first"},
"details" { "field" : "second"}
]

Backbone collection tree creation

I'm using backbone 1.1 and trying to create a collection from a 3-5 level deep tree-navigation.
A simplified version of my code looks like this.
var treeItem = Backbone.Model.extend({
defaults : {
'label' : '',
'children' : null
},
initialize : function() {
console.log('model init');
if (_.isArray(this.get('children'))) {
this.set({children : new treeItemCollection(this.get('children'))});
}
},
});
var treeItemCollection = Backbone.Collection.extend({
model: treeItem
});
var myTree = new treeItemCollection([
{ "label" : "first", "id": 1 },
{ "label" : "second", "id": 1, "children":
[
{ "label" : "second.first", "id" : 21 },
{ "label" : "second.second", "id" : 22 },
{ "label" : "second.third", "id" : 22, "children" : [
{ "label" : "third.first", "id" : 31 },
{ "label" : "third.second", "id" : 32 }
] }
]
}
]);
In my understanding this should create the deeper level child-collections correctly (as to my understanding, initialize should be called when the object is constructed thus creating the deeper levels correctly).
For some reason this doesn't seem to be the case. The second level (eg. myTree.models[0].get('children') is correctly a collection of the treeCollection type, but the 3rd level (myTree.models[0].get('children').models[0].get('children')) is just straight up JSON from the parameter object.
To me that's the weirdest part, that the second level is ok, but the third is not. The console.log in initialize() is to check, and quite right, it gets triggered 4 times, not 6.
I'm trying to understand why the 3rd level doesn't get converted to a collection.
You can overwrite the parse function in the model to do this.
var treeItem = Backbone.Model.extend({
defaults : {
'label' : '',
'children' : null
},
initialize : function() {
console.log('model init');
},
parse: function(response) {
if (response["children"]) {
response["children"] = new treeItemCollection(response["children"]);
}
return response;
}
});
this way, each time when you do fetch() or save(), it will automatically wrap your children (and their nested children, if exists) in treeItemCollection.
But this does not work when you bootstrap your data, or you are just using reset(). so you may want to overwrite the constructor method as well:
var treeItem = Backbone.Model.extend({
//other stuff shown above
constructor: function(attributes, options){
options = options || {};
options.parse = true;
Backbone.Model.call(this, attributes, options);
}
});
and it should work for your case.
We have used this pattern in many projects and we loved it. If you wanna apply it to all models/collections, and be more flexible, you probably wanna read this:
http://www.devmynd.com/blog/2013-6-backbone-js-with-a-spine-part-2-models-and-collections

iterating over collection in backbone.js

var User = Backbone.Model.extend({
defaults : {
"students" : [
{
name : "abc",
grade: "A",
school: "xyz"
}],
"interest":
{
music : "yes"
}
}
});
var UserList = Backbone.Collection.extend({
model : User,
});
var obj = new UserList({"students" : [{name:"Rax", grade: "B", school : "javiers"}, {name:"John", grade: "C", school : "loreto"}], "interest" : {music: "yes"}});
for(var i = 0; i < obj.students.length; i++) {
console.log(obj.students.at(i).get("name"));
console.log(obj.students.at(i).get("grade"));
console.log(obj.students.at(i).get("school"));
}
//i want to iterate over each students detail(name, grade and school) ..but this is giving me error " obj.students is undefined " ..why this error is coming?
First of all, there are several syntax errors, so look into console and fix these. Also, something is conceptually wrong with the object you pass to collection.
Collection is a "user list", the model is one user. So, perhaps, you should change the defaults data description. It doesn't make sense to make students an array for a user.
Also, when you create an instance of Collection, you then create a model by using create method, and not by just passing in the hash. You could instatinate the Model that way, but not the Collection.
So when you want to create a user, you pass only one "student" in, perhaps something like this (you also have to put "url" key in your Collection, otherwise it won't work):
var User = Backbone.Model.extend({
defaults : {
"students" : [{
name : "abc",
grade: "A",
school: "xyz"
}],
"interest":{
music : "yes"
}
}
});
var UserList = Backbone.Collection.extend({
model : User,
// `url` is required, otherwise Backbone will throw an error
url : '/something'
});
var userList = new UserList();
var bob = userList.create({
students : [ {
name:'bob',
grade : 'a',
school : '123'
} ],
interest : { music : 'no' }
});
console.log( bob.get('students')[0].grade );
http://jsbin.com/elusey – here, hit "edit" and take a look at the code and in the console. You should see "a" as an output.
You could actually simplify the model to this (as I told, the data structure described above doesn't really make sense for a single user):
var User = Backbone.Model.extend({
defaults : {
name : "abc",
grade : "A",
school : "xyz"
interests : ["music"]
}
});
UPD. Actually, you don't have to use create collection method in order to add models to your collection. When you create an instance of your collection you can pass in an array of models, something like this (note the difference, in your code you pass an object to a collection, but you actually need to pass an array, even if with one object in it):
var userList = new UserList([{
name:'bob',
grade : 'A',
school : '123',
interests : [ "music" ]
},{
name:'george',
grade : 'B',
school : '321',
interests : [ "drugs" ]
}]);
You can find the working example that is using this way of adding models (don't forget to look into console) here: http://jsbin.com/elusey/2/edit
Are you sure a user 'has many' students? That doesn't make much sense. However, if that is the case, you should add a definition for a student model and collection of students. Than, your user model should contain a student collection, and some logic in the set() method to transform an array of students to a students collection. If you want to handle collections/models nested under a model more gracefully, take a look at Backbone-relational.

Categories

Resources