Model.find() returnes an object or array of objects? [mongodb] - mongodb

const tours = await Tour.find()
when i use console.log(typeof tours) it shows object in console log.
but when i use console.log(tours) it shows an array of objects.
so i'm bit confused about what it actually returns back?

In JavaScript the value of typeof when used on an array is "object". The correct way to check if a variable is an array is Array.isArray() - it will return true or false depending if the argument passed is an array.

Related

AngularFire valueChanges with idField and non-existent document

If I call valueChanges on a Firestore document that doesn't exist, it returns undefined:
this.afs.doc('bad_document_ref').valueChanges().subscribe(snapshot => {
console.log(snapshot) // undefined
});
But if I call valueChanges on the same bad ref, but I pass in the idField parameter, it returns an object with just the id:
this.afs.doc('bad_document_ref').valueChanges({ idField: 'custom_doc_id' }).subscribe(snapshot => {
console.log(snapshot) // { custom_doc_id: 'bad_document_ref' }
});
I would like for the two above examples to return the same thing. I can do this by adding a pipe:
this.afs.doc('bad_document_ref').valueChanges({ idField: 'custom_doc_id' })
.pipe(map(snapshot => {
if(!snapshot) return undefined;
if (Object.keys(snapshot).length === 1 && Object.keys(snapshot)[0] === 'custom_id_field') {
return undefined;
}
return snapshot;
}))
.subscribe(snapshot => {
console.log(snapshot) // undefined
});
Is there a reason why the first two examples don't return the same thing? It seems like the logical thing to do, for the sake of consistency. Maybe there is a reason I'm not thinking of for why they would return different values?
The valueChange() method is basically the current state of your collection. You can listen for changes on the collection’s documents by calling valueChanges() on the collection reference. It returns an Observable of data as a synchronized array of JSON objects. All Snapshot metadata is stripped and just the document data is included.
When you pass an option object with an idField key containing a string like .valueChanges({ idField: 'propertyId' }); , it returns JSON objects with their document ID mapped to a property with the name provided by idField.
When the document doesn't actually exist, you would expect it to return nothing. In the first piece of code, you are not providing idField and the document doesn't exist, the observable returned undefined, which is justified. However, when you specify idField in the second piece of code, you basically say that when you return the data, you want the id of the document to be added to it. However if there is no data, there should not be any value returned, which is what you wanted to point out and which is quite justified. In other words, if the document does not exist, ideally it should return undefined even if you specify the idField parameter.
A GitHub link pointing towards the same issue says that the appropriate behavior is addressed in version 7 api.
Another GitHub link to be followed on this.
I am using:
angularFirestore.collection<Item>('items');
Note that for the object mapped I use <Item>, so maybe you can use it in your doc.

How to get certains values from Eloquent collection?

I have an Eloquent collection (already executed query) and I need to do some things with two items from this array so I need to use only or pluck methods but they dont return what I need...
$orders = Order::with('parts')->paginate(50);
$orders[0]->parts->lists('name'); // Returns names
$orders[0]->parts->lists('custom_name'); // Returns custom names
$orders[0]->parts->only(['name', 'custom_name']); // Returns nothing
$orders[0]->parts->pluck(['name', 'custom_name']); // Returns no values
The only method returns the items in the collection with the specified keys. Since Colllection keys are not those column names you specified but simple incrementing numbers you won't get result by using only method.
The pluck method retrieves all of the collection values for a given key.
so You must use
$orders[0]->parts->pluck('name', 'custom_name');
insted of
$orders[0]->parts->pluck(['name', 'custom_name']);
remove those [ ] and it should work fine.

Dereference a ReferenceField in Mongoengine

I am trying to dereference a reference field on my Flask backend and return the complete object with that certain field dereferenced.
The field I am trying to dereference is defined like this:
vouches_received = db.ListField(db.ReferenceField('Vouch'))
The way I am trying to dereference it is like this:
unverified_vouches = []
for vouch in usr.vouches_received:
unverified_vouches.append(vouch.to_mongo())
usr.vouches_received = unverified_vouches
However, when I then do:
usr.to_json()
On the object, then I get a ValidationError like so:
ValidationError: u'{...}' is not a valid ObjectId, it must be a
12-byte input of type 'str' or a 24-character hex string
The 3 dots (...) is basically the document dereferenced, it has mostly Strings, a Date Field, and some other reference fields I do not wish to dereference.
I am aware this is a valid error, as it is expecting an ObjectID for the reference field, but then arises the question, how do I succeed at dereferencing that field and return the document.
Thanks
The ListField is expecting elements of ObjectId and because you've de-referenced them it throws that error. I'm not sure this is the most elegant way but could you convert the usr.to_json() to a dict and then replace the vouches_received list with a deferenced list afterwards - I can't test it but something like?
user_dict = json.loads(usr.to_json())
unverified_vouches = []
for vouch in usr.vouches_received:
user_dict['vouches_received'].append(vouch.to_mongo())
usr_json = json.dumps(user_dict)
A better solution may be to use an EmbededDocument.

I would like to store the values in array list after iterating the select options , is it possible in Watir

I am trying to store the values of select list in an array variable
a = b.options.each {|option| puts option.attribute_value "value" }
Output :
IN PROGRESS
UPCOMING
FINAL
POSTPONED
CANCELLED
a.to_i
Is it possible to store all values which getting from attribute and store in An array
The element collections in Watir include the Enumerable module, which gives a lot of useful methods for iterating. In particular, it includes a map method that will perform a block on each element and collect the result in an array.
To store the value of all options, you can simply do:
total_list_values = #browser.options.map(&:value)
#=> ["IN PROGRESS", "UPCOMING", "FINAL", "POSTPONED", "CANCELLED"]
I coded it like this and its worked, posted if anyone wanted this
total_list_values = Array.new
body = #browser.options
body.options.each do |option|
total_list_values << option.value
end

Comparing ObjectID's in Jade and MongoDB

Jade Template Code
each member in team.members
if member == user._id
- flag=true;
Here, team is a document in the collection 'teams' in Mongo DB, and 'members' is a property having Arrays as value.
Here values of #{member} are 53fecc27bace957811633dcc and 5412a08fa51c105017b9f1fe respectively. Both are Object Id's.
Value of #{user.id} is 53fecc27bace957811633dcc
However, this comparison returns as false and flag is never set to true.
Why is it so?
EDITED FOR CLARITY:
The mongodb-native driver uses a custom ObjectID type. Even if the ObjectIDs are the same, member and user._id would still refer to two distinct objects, and therefore the comparison fails.
Here's a simplified example of what I'm talking about. In the example below I have a constructor function for a TestObject (simulating the mongo ObjectID). I instantiate two objects (i.e. x1 and x2) both with the same parameter. While x1 and x2 are instances of the same object and both were created with the same arguments, they are actually just two different objects with the same data/payload. Therefore, the first direct comparison fails, because they in fact are not the same. To take the simulation a bit further, I added a prototype method .equals() which ensures that both objects are instances of TestObject and the payloads are identical.
function TestObject(data) {
this.payload = data;
}
TestObject.prototype.equals = function(anotherObject) {
return (anotherObject instanceof TestObject) && (this.payload === anotherObject.payload);
};
var x1 = new TestObject(1), x2 = new TestObject(1);
console.log(x1 == x2); // <-- false
console.log(x1.equals(x2)); // <-- true
You can compare them by converting the ObjectIDs to strings.
each member in team.members
if member.toString() == user._id.toString()
- flag=true;
Another possible solution would be to use the ObjectId .equal() method:
each member in team.members
if member.equals(user._id)
- flag=true;
MongoDB objectIds are probably not simple strings. As per docs, they are BSON types.
It's possible that member and user._id are two different objects that is why a "reference equals" comparison is failing, even though their string representations are the same.
On a related note, it's a bad idea to use MongoDB generated object IDs in your application. A more robust design would be to have your own identifier for every record type.