mongodb - mapReduce() scope - Undefined values are converted into null values - mongodb

If I put a variable with an undefined value into the "scope" parameter of mapReduce(), then the map function will receive the variable with a null value (instead of the undefined value). Is that correct?
For example (javascript skeleton for the "mongo" command):
db.mycol.mapReduce(
f_map,
f_reduce,
{
scope: { myvar: undefined}
}
);
function f_map()
{
print("myvar: " + myvar);
}
That will print "myvar: null" (instead of "myvar: undefined") into the server log (into the replicaset member log). Are undefined values converted automatically to null values when passing through mapReduce()?

Yes undefined values get translated into null values in mongodb's v8 engine.
The reason for this is to keep backwards compatibility with the older Spider Monkey JS engine and not break existing code that relied on that behaviour.

Related

Is there any difference between initializing with empty values or null value?

Is there any difference between these two part of code? (I am specially using Flutter/Dart but also interested to know about this in any other popular languages like C/C++, Java, JS, Python, etc.)
Code1:
String a = null; (in Flutter: a = null as String; )
List<T> = null; (in Flutter: List<T> = null as List<T>;)
Code 2:
String a = '';
List<T> = [];
With Dart nullsafety your first examples are invalid (assuming you meant to have a variable name on your List). If a variable can contain null the type needs a '?' suffix:
String? a = null;
List<T>? b = null;
But with or without nullsafety or '?', use of the variables in your second example won't result in runtime errors. For example a.trim(): if a is null a runtime error will occur because you're trying to call (null).trim(). In your second example no error because there is a String object to access, even though that String object is empty of characters. Same for your List: b.forEach((e) {}) when b==null a runtime error occurs because there's no Object to find forEach() - i.e. the runtime doesn't know what to do with (null).forEach(). In your second example the forEach() doesn't execute the function because List b is empty, but there's no runtime error because there's an Object to call forEach() on.
In C: NULL for pointers is usually synonymous with 0. The result of trying to access memory address NULL is "undefined" in C, because it could be valid as 0x00 in some instances like embedded systems or low-level system code, but will usually result in your process being terminated (crash).

how to handle empty array for text widget in build method?

How would I handle the objectA[0].name (a string) in the build method if the array is empty?
Text(objectB.objectC.objectA[0].name),
Assuming the array is objectC you can do something like:
Text(objectC.isEmpty? "" :objectC[0].name)
You can read more about ternary operators in dart here
There isn't a great way to do this inline but with a simple extension method to return the original null or the iterable depending on whether the item is null or empty you can make it work.
First
Extension Method
(requires dart v2.7 - update in your pubspec.yaml file)
extension IterableExtension<T> on Iterable<T> {
Iterable<T> get nullWhenEmpty =>
this == null || this.isEmpty ? null : this;
}
Second
To handle null values while you're traversing an object you can use the Dart's conditional member access operator (?.). This operator will only continue with the right-hand side if the left-hand side of the operator is not null. Use the elementAt method on a an iterable to be able to use the ?. operator in the chain. Then, use the ?. operations with the if null operator (??) to get your default value.
Solution
final String value = objectB?.objectC?.objectA?.nullWhenEmpty?.elementAt(0)?.name;
Text(value ?? 'Default Text');
You can, of course, inline the above code instead of using an additional variable.
Resources
Dart Language Tour: Other Operators
Dart Language Tour: Classes
Maybe checking if the list has an element, using isNotEmpty
child: (objectB.objectC.objectA.isNotEmpty)
? Text(objectB.objectC.objectA[0].name)
: Container(),

Is Dart pass by reference? [duplicate]

This question already has answers here:
What is the true meaning of pass-by-reference in modern languages like Dart?
(3 answers)
Closed 1 year ago.
In this post: Flutter video_player dispose
I asked how to dispose something so I can re-use it again. The answer provided works correctly but it left me with this question:
why does this code work as intended? eg it disposes the old instance from videoController using oldController
final oldController = videoController;
WidgetsBinding.instance.addPostFrameCallback((_) async {
await oldController.dispose();
_initController(link); //contains reassignment of videoController = VideoController.network(...)
});
in C or similar languages, a use of pointer is needed (or should I say my preferred way). To pass the reference, assign a new value to it and then take care of the old one.
Sorry that my answer left you with a confusion. Yes, in Dart you work with references to objects, just like in Java. I'll give a short example that should make it clear for you why this code works as intended:
void main() {
final t = Test(Test());
t.removeField();
}
class Test {
Test t;
Future<void> removeField() async {
print('current field: $t');
Future.delayed(Duration(seconds: 2)).then((_) => print('delayed value: $t'));
t = null;
}
Test([this.t]);
}
prints:
current field: Instance of 'Test'
delayed value: null
In this case, field's value is set to null first and then 2 seconds later callback executes. It accesses object's field, but it's already null. But if we make it like this:
final old = t;
Future.delayed(Duration(seconds: 2)).then((_) => print('delayed value: $old'));
it prints:
current field: Instance of 'Test'
delayed value: Instance of 'Test'
We stored previous value of the field and passed it to the callback, so it won't access nulled field.
Dart does not support passing by reference. Dart is only passed by value, just like Java. Java also does not support reference passing.
Is Java “pass-by-reference” or “pass-by-value”?
https://stackoverflow.com/a/40523/1737201
Below is a little proof.
void main() {
// The variable "myVar" is a "lvalue" (storage of value)
// Now we assign the value to "myVar" via "rvalue" "Object()"
final myVar = Object();
// Remember the old value
final oldObject = myVar;
// Now we will try to pass by reference.
// We assume that we will pass the reference of storage ("lvalue")
// ("myVar" im our case) because we cannot reference the value (pure data)
// because the value does not contain storage location information.
tryChangeMyVarByRef(myVar);
// Check the result passing by reference
// If storage of value was passed by its reference then changing
// the value in this storage should have effect.
assert(!identical(myVar, oldObject));
// Epic fail because Dart does not support pass by refernce.
print('WOW, it works!');
}
void tryChangeMyVarByRef(Object referencedStorgeOfValue) {
// Try change the value stored in referenced storage of value
referencedStorgeOfValue = Object();
}
EDIT:
The value (or more correct rvalue which means a data whitout any storage) cannot have an address because the value is just a data. In programming impossible to reference the data (because there are no any way to do that) but possible to reference the storage of data (eg. address of variable) because the storage are always has some location rather than data (data only can be stored at some location but not referenced because data can be replaced at any time at this location and thus this cannot be called as reference to data because this can be incorrect after data reassigment would be perfomed but should be only called as reference of some storage of some data).
In the programming the term "pass by reference" means: pass the reference (address of the location) of the value storage (that is, the address of some varibale with any data but not the address of this data).
This allows to replace (but not just change) stored data at some location becuase the storage was referenced (address of laocation was known).
Which means only one thing: you pass reference of the variable where some value are stored.
And this does not means the reference of some value as many newbie wrongly think (who never used C or C++ language).
Another important thing is that the in Dart the object (or instances) itself are references because they are boxed (the values was stored in the heap).
This creates illusion that you pass by reference but at the same time you pass by value the reference (where reference as value is passed by value). Pass by value the reference is not the same as pass by reference the reference.
Free advice to newbie: Learn the C or C++ programming languages to find out the difference between the following things:
Pass by value the reference
Pass by reference the reference
In both cases the value itself is a reference but in first case you pass the value (reference) by value but in second case you pass the value (reference) by reference.
Enjoy!

FilterOperator bug in using quotes, same code different behavior across systems/time

this.getView().getModel().read("/QualificationProficiencySet", {
filters: [new sap.ui.model.Filter({
path: "Qobjid",
operator: sap.ui.model.FilterOperator.EQ,
value1: nQObjid
})],
success: function(data) {
that._profData = data.results;
that._oQuickView.setModel(new sap.ui.model.json.JSONModel(that._profData), "proficiencyModel");
// delay because addDependent will do a async rerendering and the actionSheet will immediately close without it.
jQuery.sap.delayedCall(200, that, function() {
that._oQuickView.openBy(oLink);
});
},
error: function(evt) {}
});
nQObjidis of type string - always.
Yesterday on our development system I saw the error
"Invalid parametertype used at function 'eq' (Position: 8)"
I noticed that the filter was appended in the URL without single quotes around the value of nQObjid. Strange because at the moment it's added as the value of the filter operator it's clearly a string. I couldn't find any related issues, but I put a (dirty) workaround in place by doing value1: "'"+nQObjid+"'".
This worked, until today, same system, didn't change the code, but suddenly the quotes are part of the value inside the gateway. So I remove the "'"again and tested, works. Then I transport the solution to production to find out that I now have the same problem on production with "Invalid parametertype used at function 'eq'.. Another user on production does not have this issue, so I'm a bit lost.
Similar issue: new SAPUI5 updat to 1.42 has odata bug "Invalid Parameters...
This may not solve your problem but it's too long for a comment, that's why I am posting it here:
When doing a read request, the framework is making a call to a helper class: V2 ODataModel.js Line #4231
aUrlParams = ODataUtils._createUrlParamsArray(mUrlParams);
The helper class then calls a private method: ODataUtils.js Line #72
return "$filter=" + this._createFilterParams(aFilters, oMetadata, oEntityType);
This private method is doing a bunch of stuff, most importantly calling another private method which is actually building the strings ODataUtils.js Line #128
sFilterParam = that._createFilterSegment(oFilter.sPath, oMetadata, oEntityType, oFilterSegment.operator, oFilterSegment.value1, oFilterSegment.value2, sFilterParam);
One of the first thing this method does is formatting your value, and I guess here is where your problem occurs: ODataUtils.js Line #393
oValue1 = this.formatValue(oValue1, sType);
The formatValue function takes your value and its Edm.Type and depending on that type does different stuff. If your objectId is a string, then it should put single quotes at the beginning and the end: ODataUtils.js Line #468
sValue = "'" + String(vValue).replace(/'/g, "''") + "'";
If the type is undefined or some weird value that UI5 doesn't know, then your value is simply cast to a String (which is probably what happens in your case).
Why is the type undefined or weird? That's where you come in... you have to do a little debugging to find out what the actual values are. If the UI5 code is unreadable you can put sap-ui-debug=true as an URL parameter:
my.sap.system.com:8000/sap/bc/ui5_ui5/sap/ztest/index.html?sap-ui-debug=true
If it's a timing issue (metadata has not been loaded for whatever reasons) then wrapping your code in a Promise might help:
var oModel = this.getView().getModel();
oModel.metadataLoaded().then(function() {
oModel.read("/QualificationProficiencySet", {
// ...
});
}

using unset in CakePHP MongoDB

I am using Ichikawa CakePHP MongoDB plugin. I have a problem in using unset in it. I have tried the command in shell:
db.patents.update({}, {$unset : {"lv.2" : 1 }},{'multi':true})
db.patents.update({},{$pull:{pid:"2"}},{'multi':true})
These are working fine.
But when I am converting them to CakePHP command as follows:
$this->Detail->updateAll(array('$unset'=>array('lv.2'=>1,array('multi'=>true))));
Then it doesn't work and gives error:
MongoCollection::update(): expects parameter 1 to be an array or object, boolean given
Can anyone help me to figure out the problem.
Thanks.
There are no conditions
The error message means that the query being generated is the equivalent of:
db.details.update(true
This can be confirmed by checking the query log (easy if you're using debug kit).
How is that happening
The second parameter for model updateAll is missing, which means it will have the default:
public function updateAll($fields, $conditions = true) {
^
return $this->getDataSource()->update($this, $fields, null, $conditions);
}
Therefore in the mongodb datasource class - the conditions passed are true:
public function updateAll(&$Model, $fields = null, $conditions = null) {
^
As a consequence, the resultant update statement has true as the first parameter, not an array.
Correct syntax
The correct syntax for such a query is:
$this->Detail->updateAll(
array('$unset'=>array('lv.2'=>1))
array() # <- do not omit this
);
Note that it's not necessary to specify 'multi'=>true as the datasource does that for you, especially not in the fields argument.