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)
Related
{
"accounts" : {
"-account1" : {
"email" : "test#example.com",
"name" : "John doe",
"online" : false,
"profilePic" : "example.com/img.png",
"username" : "jonh_doe"
"tokens" : [
"token11111",
"token22222",
"token33333"]
},
"-account2" : {
"email" : "testymctest#example.com",
"name" : "Jane doe",
"online" : false,
"profilePic" : "example.com/img.png",
"username" : "jane"
"tokens" : [
"token44444",
"token55555",
"token66666"]
}
}
}
My user data is structured as above and I'm trying to determine if -account1 has a token with the value "token11111"
Other Firebase examples suggest using snapshot, but I haven't found an example that drills down into a child element to find a value.
This is what I've tried
firebase.database().ref('accounts/-account1/tokens')
.equalTo(newToken)
.once('value')
.then(function(tokens) {
if (tokens.exists()) {
//Token already exists
}
else{
//Push new token to db
}
});
When you get an array-like object back from a Firebase snapshot (the keys are numbers starting a 0), you deal with it just like a regular JavaScript array:
var ref = firebase.database().ref('/accounts/-account1/tokens');
ref.once('value').then(function(snap) {
var array = snap.val();
for (var i in array) {
var value = array[i]
console.log(value);
if (value == 'whatever') { ... }
}
});
This will iterate and print each value. You can look for any value that you like in that loop. Or you can includes(x) on the array in JavaScript ES2016.
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;
}
I am trying to add to an existing array in my mongoDB. Here is what I have, but it is of course incorrect because all the data gets wiped out after it tries to add it:
db.cardKeeper.update(
{_id: ObjectId('5621c5ac30895e5776e4d1ea')},
{
$push:{'cardKeeperApp.appData.cardDecks':deckObject}
}
)
deckObject which is the object I am trying to add to the array looks like this
var deckObject = {
name: productName,
searchName: productItem,
price:{
purchasePrice: productCost,
averageWorth: priceAverageFixed,
lowWorth: lowestSoldAmount,
highWorth: highestSoldAmount
}
}
and as you can see cardKeeperApp.appData.cardDecks is my array which holds more info that looks just like deckObject
If it helps here is the full object, I am trying to add to the cardDecks array. I have marked fields as null
{
"_id" : ObjectId("5635ddf82f4c220f4f932af2"),
"cardKeeperApp" : {
"appData" : {
"cardDecks" : [
{
"name" : "Some Name",
"searchName" : "Some+Name",
"price" : {
"purchasePrice" : null,
"averageWorth" : null,
"lowWorth" : null,
"highWorth" : null
}
}
],
"allDeckTotalWorth" : null
}
}
}
I found the solution. findAndModify by query:{_id:ObjectId} and then update and push:
db.cardKeeper.findAndModify({query:{_id: ObjectId('5635ddf82f4c220f4f932af2')},
update: {$push:{'cardKeeperApp.appData.cardDecks': deckObject}},
new:true}, function (err, doc) {
res.json(doc);
});
I'm trying to delete a subdocument in mongoDb but can't succeed in it. I've tried with $update,$push and $pull but I'm not successful.
I have the following document:
db.users.findOne({"_id": ObjectId("545677a9e4b0e0ef9379993c")})
{
"_class" : "com.xxx.xxx.server.da.User",
"_id" : ObjectId("545677a9e4b0e0ef9379993c"),
"bookSummaries" : [
{
"_id" : ObjectId("545677e7e4b0e0ef9379993d"),
"isbn" : "2746969644"
"title": "test title"
},
{
"_id" : ObjectId("546a522a44ae4f5e652fdca7"),
"loanSummaries" : [
{
"loanStatus" : "REQUESTED",
"loanId" : "5473992044aec466a619290c"
},
{
"loanStatus" : "REQUESTED",
"loanId" : "5473997d44aec466a619290d"
},
{
"loanStatus" : "REQUESTED",
"loanId" : "547605a744ae0f0d558ae757"
}
],
"testArray" : [
{
"title" : "Back to the future",
"id" : "test"
},
{
"title" : "Back to the future",
"id" : "test2"
},
{
"title" : "Back to the future",
"id" : "test3"
},
"test ",
"test ",
"test 2",
"test 2",
{
"loanStatus" : "REQUESTED"
}
],
"title" : "Back to the future"
}
]
}
and I'm trying to create the queries to:
delete the whole "testArray" subdocument for only this specific subdocument
delete a specific loanSummaries give its loanId for this specific subdocument
Can you help me creating those queries? I've seen several post like this one, but it is not the same problem.
Thanks a lot
I recently had the same problem where I had to remove a nested subarray. In the query you need to identify the exact object that you want to remove, and then in your update query you can use the $ sign as index for the object in the array that you want to pull.
var query = {
"_id" : ObjectId(someUserId),
"bookSummaries._id" : ObjectId(bookId), //might also work with isbn as long as it is uniq
"bookSummaries.loanSummaries.loanId" : loanId
};
var updateQuery = {
"$pull" : {
"bookSummaries.$.loanSummaries" : {
"loanId": loadId
}
}
}
Update
I tried the following queries in my shell which worked fine. You will have to enter the appropirate ids.
var query = { "_id" : ObjectId("53b73b1108fe927c0e00007f"), "bookSummaries._id" : ObjectId("53b73b1108fe927c0e00007f"), "bookSummaries.loanSummaries.loanId" : "53b73b1108fe927c0e00007f" }
var updateQuery = { "$pull" : { "bookSummaries.$.loanSummaries" : { "loanId": "53b73b1108fe927c0e00007f" } } }
Update 2
If you already know the index of item/object you want to remove you can use the queries below in order to achieve this.
Find the document you want to edit
var query = {
"_id" : ObjectId(someUserId),
};
Unset the object you want to remove
var update1 = {
"$unset" : {
"bookSummaries.1.loanSummaries.2" : 1
}
}
Pull the object which has the value null.
var update2 = {
"$pull" : {
"bookSummaries.1.loanSummaries" : null
}
}
And to remove you can basically use the same queries.
Find the document you want to edit
var query = {
"_id" : ObjectId(someUserId),
};
Unset the object you want to remove
var update1 = {
"$unset" : {
"bookSummaries.0.testArray" : 1
}
}
Because MongoDB provides a full JavaScript environment you can easily manipulate the document and save the data back to the db.
*Note: if you are using MongoDB with php or python etc. there are equivalent ways to do that.
1.to delete whole "testArray" subdocument for only this specific subdocument for example index(1) do
db.users.find({"_id": ObjectId("545677a9e4b0e0ef9379993c")}).forEach(function (user) {
delete user.bookSummaries[1].testArray;
//Saveing the changes
db.users.save(user);
});
to delete a specific loanSummaries give its loanId for this specific subdocument for example id 5473992044aec466a619290c do
db.users.find({"_id": ObjectId("545677a9e4b0e0ef9379993c")}).forEach(function (user) {
var loanToDelete = "5473992044aec466a619290c";
var loanIndexToDelete = -1;
var i;
for(i in user.bookSummaries[1].loanSummaries) {
if(user.bookSummaries[1].loanSummaries[i].loanId === loanToDelete) {
loanIndexToDelete = i;
break;
}
}
if (loanIndexToDelete > -1) {
delete user.bookSummaries[1].loanSummaries[loanIndexToDelete];
}
//Saving the changes
db.users.save(users);
});
I had to do something similar but delete multiple subdocuments instead of just one. My query included an array of ids and this worked for me:
User.updateOne(
{ _id: userId },
{
$pull: { bookSummaries: { _id: { $in: ids } } },
});
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