Angular / Meteor: Array is undefined - javascript

I'm building an Angular / Meteor application, using Meteor's reactivity to populated an Angular model. It is all working fine until I start working with arrays.
// get sentence
$scope.sentence = $meteor.object(Sentences, $stateParams.sentenceId);
// related sentences
$scope.relatedSentences = $meteor.collection(function() {
return Sentences.find({_id: { $in: $scope.sentence.relatedSentences }});
});
I get this error on the JavaScript console
Error: $in needs an array
at Error (native)
at Object.ELEMENT_OPERATORS.$in.compileElementSelector (http://localhost:3000/packages/minimongo.js?af9eb9d7447544ca9b839a3dcf7ed2da2209b56c:1894:15)
at http://localhost:3000/packages/minimongo.js?af9eb9d7447544ca9b839a3dcf7ed2da2209b56c:1576:19
at Function._.each._.forEach (http://localhost:3000/packages/underscore.js? 0a80a8623e1b40b5df5a05582f288ddd586eaa18:164:22)
In the Mongo / Meteor console
meteor:PRIMARY> db.sentences.find({_id: "sp75iWPNqpbp2ypmy"});
{ "_id" : "sp75iWPNqpbp2ypmy", "sentence" : "Here is sentence 1 ", "language" : "en", "level" : "A1", "public" : true, "relatedSentences" : [ "wNs4ByDq7t396WLM3" ] }
And
meteor:PRIMARY> db.sentences.find({_id: { $in: [ "wNs4ByDq7t396WLM3" ] }});
{ "_id" : "wNs4ByDq7t396WLM3", "sentence" : "Here is sentence 0 ", "language" : "en", "level" : "A1", "public" : true, "relatedSentences" : [ ] }
I then commented out the failing find and have outputted the objects to html
$scope.sentence = $meteor.object(Sentences, $stateParams.sentenceId);
$scope.test = typeof $scope.sentence.relatedSentences;
Sentence: {{sentence}}<br/>
Related: {{sentence.relatedSentences}}<br/>
Typeof: {{test}}
Results
Sentence: {"autorunComputation": {"stopped":false,"invalidated":false,"firstRun":false,"_id":47,"_onInvalidateCallbacks": [null,null],"_parent":null,"_recomputing":false},"_id":"oFMp7swYyQsXkYsKz","sent ence":"Here is sentence 2","language":"en","level":"A1","public":true,"relatedSentences": ["wNs4ByDq7t396WLM3"]}
Related: ["wNs4ByDq7t396WLM3"]
Typeof: undefined
The Array is marked as undefined, but it is clearly shown in the full object. What am I missing?
EDIT
When running the above test on Firefox it returns an object
Related: ["wNs4ByDq7t396WLM3"]
Typeof: object
Related issue

$scope.test is only bound one time when this code initially runs. There is no data binding, so even if $scope.sentence.relatedSentences changes, test will not. The issue is that $scope.sentence.relatedSentences is populated asynchronously.
This would also apply to $scope.relatedSentences -- you are trying to set it initially before $scope.sentence.relatedSentences is available. You can use .subscribe on the value returned from .object to set this once the data is available.
$scope.sentence.subscribe().then(function () {
$scope.relatedSentences = $meteor.collection(function() {
return Sentences.find({_id: { $in: $scope.sentence.relatedSentences }});
});
});

Related

Update database entry using mongoose

Hello i am using mongoose.
I have built this query that finds my desired project :
const projects = await ClientManagers.findOne({'project.contactPerson.work_email' : 'testing#email.com'} , { 'project.$.companyName': 1 });
this returns an object from my database like this :
{
'projectName' : 'x',
'companyName' : 'x bv'
}
How can i update the company name to be 'Y bv' instead of 'x bv'.
Assuming this is your document structure,
{
"_id" : ObjectId("5f2ae5a4b1549ac0460920dd"),
"projectName" : "A",
"project" : [
{
"companyName" : "T1",
"contactPerson" : {
"work_email" : "t1#gmail.com"
}
},
{
"companyName" : "T2",
"contactPerson" : {
"work_email" : "t2#gmail.com"
}
}
]
}
Single Update updateOne()
If you know email will be unique and want to update single document then use updateOne().
first is query part to find condition, email t1#gmail.com
second is set/update part, here $ is for array because project is an array, update companyName to T1 Company
await ClientManagers.updateOne(
{ 'project.contactPerson.work_email': 't1#gmail.com' },
{
$set: { "project.$.companyName": "T1 Companmy" }
}
)
Multiple Update updateMany()
If email is not unique and want to update everywhere then use updateMany(), it will update every matching documents.
await ClientManagers.updateMany(
{ 'project.contactPerson.work_email': 't1#gmail.com' },
{
$set: { "project.$.companyName": "T1 Company" }
}
)
Not suggesting update() method to use, because its deprecated in mongoose and will give Deprecation Warnings
, this function is replaced with updateOne(), updateMany() and replaceOne() methods.
Good start. Mongo has better documentation with examples. I suggest you to refer that also.
use update
db.collection.update({companyName:'x bv'}, {"$set":{"companyName":y}})
Mongo is case sensitive. So name should match exactly.
update updates one document. To update multiple, use updateMany or multi:true option with update or findOneAndMondify for one update for find and update case.

MongoDB How to filter db.adminCommand output

does anybody know how to filter mongodb db.adminCommand output? Because if I run this command db.adminCommand({ "currentOp": true, "op" : "query", "planSummary": "COLLSCAN" }) I get a huge JSON output but I'm only interested in some fields ( like secs_running, op, command, $db)
Many thanks!
You can add the filters straight to the command object like the following:
var commandObj = {
"currentOp" : 1,
"waitingForLock" : true,
"$or" : [
{
"op" : {
"$in" : [
"insert",
"update",
"remove"
]
}
},
{
"command.findandmodify" : {
"$exists" : true
}
}
]
};
db.adminCommand(commandObj);
You can see some filter examples on the MongoDB docs: https://docs.mongodb.com/manual/reference/method/db.currentOp/#examples
Just re-read your question and I think you might of meant just projecting fields back from the database that you care about? if that's the case you can just execute a map on top of the current results so you only see what you care about?
db.adminCommand(commandObj).inprog.map(x => x.opid};

Firebase query DataSnapshot val() returning null

My Firebase structure is below
{
"Test1 Lab" : {
"Equipment" : "3-D printer",
"Hours" : "7AM-6PM",
"Location" : "Library",
"Name" : "Digital Lab"
},
"Test2 Lab" : {
"Equipment" : "Oculus",
"Hours" : "7AM-6PM",
"Location" : "Hall",
"Name" : "Test Lab"
}
}
The top level is called "makerspace". I am trying to get the Name, Equipment, and Hours of the item where the Location is "Library" I ran the code:
var red = database.ref('makerspace');
return red.orderByChild('Location').equalTo("Library").once('value').then(function(snapshot){
console.log(snapshot.child("makerspace").child("Name").key);
});
And I get "Name". However, when I change .key to .val(), I should expect to get "Digital Lab", but I get null. I don't know how to fix this.
The snapshot is already on the makerspace node, so it should be:
var red = database.ref('makerspace');
return red.orderByChild('Location').equalTo("Library").once('value').then(function(snapshot){
console.log(snapshot.child("Name").val());
});
Try this
var red = database.ref('makerspace');
return red.orderByChild('Location').equalTo("Library").once('value').then(function(snapshot){
snapshot.forEach(function(data) {
console.log(data.val());
});
});
I would recommend to access snapshot data like this,
red.orderByChild('Location').equalTo("Library").once('value').then(function(snapshot){
console.log(snapshot.val()); <==========
// result would be
{ "Test1 Lab" : { "Equipment" : "3-D printer","Hours" : "7AM-6PM","Location" : "Library","Name" : "Digital Lab" } }
}
To get properties you can do,
snapshot.val()['Test1 Lab']['Name'] or snapshot.val()['Test1 Lab'].Name
snapshot.val()['Test1 Lab']['Hours']
Now you can get 'Test1 Lab' using Object.keys(snapshot.val())[0]
snapshot.val() is like JSON Object, so just access its properties like you did for objects. No need to use child() method to access data.

Set a value with mongoose in NodeJS

I have a NodeJS application that communicates with an Angular app. This is a simplified version, but I'll try to explain my problem:
I will get a value from the socket connection, for example:
{
Id : "1",
Checked : true,
TeamName : "Team1"
}
I want to update the mongoDb with mongoose so that every person with the TeamName : "Team1" gets the value Checked : true.
I have done something like this:
relayModel.find({TeamName : 'Team1'},
{'$set' :{Checked: true}},function(err,docs){
if(err){
console.log("Could not save value for relay runner: ", err);
}
else{
console.log("The runners updated: ",docs)
}
But I get the error:
Could not save value for relay runner:
{ [MongoError: Can't canonicalize query:
BadValue Unsupported projection option:
$set: { Checked: true }] name: 'MongoError' }
This really is well documented. Will go away for sure, but just to explain for you:
relayModel.update(
{ "TeamName": "Team1" },
{ "$set": { "Checked": true } },
{ "multi": true },
function(err,numAffected) {
if (err) throw err;
console.log( "updated n docs: %s", numAffected );
}
);
So the .update() with a "multi" option affects more than one document, and without it it just affects the first document matched. The returned values in the callback are the standard err and the "number of documents affected".
Therefore basically speaking:
You actually need and operator that "updates" in order to affect and update.
You set "multi" for more than one document and you get only the number returned as well as using the $set operator to just affect the field that you want to change.

How to get data from json in order to save them in database?

I am beginner in Javascript/jQuery and I am working on an interface made with KnockoutJS, so I have several models. I would like to save all the data in the database but I don't know how to do it.
I started with :
self.save = function() {
var data = ko.toJS(self);
var test = ko.toJSON(self);
console.log(test);
}
$.ajax({
url: "myURL",
data: {'carrier': data.carrier},
type: "POST",
});
and this is the result of the console.log :
{"id":1,"carrier":"1","Settings":[{"id":1,"price":{"id":1,"DeliveryStandard":"3.00","DeliveryExpress":"6.00","Details":{"id":1,"Standard":[{"id":1,"fromPrice":0,"maxPrice":"45.000"}],"Express"[{"id":1,"fromPrice":0,"maxPrice":"66.000"}]}}}}]}
I can get the value of carrier by using data.carrier but I don't know how to get the other data like DeiveryStandard, DeliveryExpress, fromPrice, maxPrice ...
Have you got an idea?
Thanks you in advance, and sorry if my question is silly!
If you format your JSON into a more readable format, with indenting, it makes it a lot easier to understand:
(though it should be noted that it is only technically JSON while in a string format, outside of that it is just a standard javascript object)
{
"id":1,
"carrier":"1",
"Settings":[
{
"id":1,
"price": { "id":1,
"DeliveryStandard":"3.00",
"DeliveryExpress":"6.00",
"Details": { "id":1,
"Standard": [{"id":1,
"fromPrice":0,
"maxPrice":"45.000"
}],
"Express" //Missing semi-colon
[{"id":1,
"fromPrice":0,
"maxPrice":"66.000"
}]
}
}
}}//One too many closing braces
]
}
First thing to note is you have 2 syntax errors, highlighted above with comments. So fix them first! (Though I wonder if they are typos as you seem to have it working at your end)
Then we can look at the structure tree to work out where the values you want are...
DeiveryStandard and DeliveryExpress are both properties of an object assigned to price, which it a property of the first item in the Settings array. So you can access them like so:
var DeliveryStandard = data.Settings[0].price.DeliveryStandard;
var DeliveryExpress= data.Settings[0].price.DeliveryExpress;
fromPrice and maxPrice are found multiple times, in both Standard and Express items. So you need to decide what version you need. If you want Standard then you can get the first item of the Standard array like so:
var standardObject = data.Settings[0].price.Details.Standard[0];
Which you can then access the properties of like:
var fromPrice = standardObject.fromPrice;
var maxPrice = standardObject.maxPrice;
I am sure you can work out how to get the Express version of the same data!
From what you seem to have been able to work out on your own, I think your problem is not knowing how to deal with the arrays. Note that arrays are defined with square brackets [], and elements within an array should be accessed with a zero-based index, for example: array[0] for the first element, and array[1] for the second element.
This should work.
console.log(data.Settings[0].price.DeliveryStandard);
Fixed some errors in your JSON.
var j = {
"id" : 1,
"carrier" : "1",
"Settings" : [{
"id" : 1,
"price" : {
"id" : 1,
"DeliveryStandard" : "3.00",
"DeliveryExpress" : "6.00",
"Details" : {
"id" : 1,
"Standard" : [
{
"id" : 1,
"fromPrice" : 0,
"maxPrice" : "45.000"
}
],
"Express": [
{
"id" : 1,
"fromPrice" : 0,
"maxPrice" : "66.000"
}
]
}
}
}
]
};
alert(j.Settings[0].price.DeliveryStandard);
alert(j.Settings[0].price.DeliveryExpress);
alert(j.Settings[0].price.Details.Standard[0].fromPrice);
alert(j.Settings[0].price.Details.Standard[0].maxPrice);

Categories

Resources