mongo cursor findOne - javascript

I'm trying to open a stream of data from mongoDB by querying a field with an array of values, and return only one record per index of array.
var cursor = Collection.findOne({'lastName': { $in: [arrayOfLastNames]}}).cursor();
cursor.on('data', function (record) {
//do something with record
})
for whatever reason, it is pulling multiple records per index of arrayOfLastNames. The .findOne() method is behaving as .find() would.
Any suggestions as to why this is happening, or possible alternatives to this implementation would be greatly appreciated.

You're running into issues because you used a cursor. From the mongoDB documentation, "You cannot apply cursor methods to the result of findOne() because a single document is returned."
From your comment, you want to call findOne once for every item in the array since $in with findOne will find the first document according to the "natural order" of the document that matches any item in the array (you might also consider just using a general find honestly, since then your cursor solution will work).

Related

Firestore Array of map not updating

So I'm working on a personal project to learn react-native and Firestore.
I have a DB like this:
And I want my code to add a new battery in the array batteries.
The elements in the array are just a map{string, string}
The problem is that when I update the array with a new brand that's work but if I want to update it with the same brand again have,
so having by the end
batteries[0]: {'brand': 'cestmoi'}
batteries[1]: {'brand': 'cestmoi'}
The DB doesn't update, doesn't have any error or so.
I don't understand why and I followed their tutorial. Here is my code:
async function addData(collection, doc, value) {
console.log(`Add data ${value.brand}`)
try {
const result = await firestore()
.collection(collection)
.doc(doc)
.set({
batteries: firestore.FieldValue.arrayUnion(value)
})
console.log(result);
return result;
} catch (error) {
return error;
}
}
I use try-catch by habit but I don't know if the then...catch is better or not.
As already #windowsill mentioned in his answer, there is no way you can add duplicate elements in an array using client-side code. If your application requires that, then you have to read the entire array, add the duplicates and then write the document back to Firestore.
However, if you want to update an existing element in an array of objects (maps) then you have to use arrayUnion with the entire object. If you want to understand the mechanism better, you can read the following article which is called:
How to update an array of objects in Firestore?
arrayUnion says that it "adds elements to an array but only elements not already present". Maybe it does a stringify or something to check equality and therefore doesn't add the new element. I think you'll have to 1. get the current list, 2. add your element, 3. set the batteries field to the updated list.

Meteor MongoDB Filter Parent Records by Child Fields

How would I go about filtering a set of records based on their child records.
Let's say I have a collection Item that has a field to another collection Bag called bagId. I'd like to find all Items where a field on Bags matches some clause.
I.e. db.Items.find( { "where bag.type:'Paper' " }) . How would I go about doing this in MongoDB. I understand I'd have to join on Bags and then link where Item.bagId == Bag._id
I used Studio3T to convert a SQL GROUP BY to a Mongo aggregate. I'm just wondering if there's any defacto way to do this.
Should I perform a data migration to simply include Bag.type on every Item document (don't want to get into the habit of continuously making schema changes everytime I want to sort/filter Items by Bag fields).
Use something like https://github.com/meteorhacks/meteor-aggregate (No luck with that syntax yet)
Grapher https://github.com/cult-of-coders/grapher I played around with this briefly and while it's cool I'm not sure if it'll actually solve my problem. I can use it to add Bag.type to every Item returned, but I don't see how that could help me filter every item by Bag.type.
Is this just one of the tradeoffs of using a NoSQL dbms? What option above is recommended or are there any other ideas?
Thanks
You could use the $in functionality of MongoDB. It would look something like this:
const bagsIds = Bags.find({type: 'paper'}, {fields: {"_id": 1}}).map(function(bag) { return bag._id; });
const items = Items.find( { bagId: { $in: bagsIds } } ).fetch();
It would take some testing if the reactivity of this solution is still how you expect it to work and if this would still be suitable for larger collections instead of going for your first solution and performing the migration.

only return document _id on mongoose .find()

I update 100's of documents every second by pushing new data to an array in its document. To get the document of which I am going to add data to, I use the mongoose .find().limit(1) function, and return the whole document. It works fine.
To help with some memory and cpu issues I have, I was wondering how I could get find() to only return the id of the document so I can use that to $push or $set new data.
Thanks.
You want to use Projection to tell your query exactly what you want off of your objects.
_id is always included unless you tell it not to.
readings = await collection
.find({
name: "Some name you want"
})
.project({
_id: 1 // By default
})
.toArray();
You could use the distinct method in order to get an array of _id for your query.
Follow this question
As mentioned by #alexmac, this works for me:
collection.find({}, '_id')

Meteor: retrieve value from document in collection

I have a Collection named "balance". I want to get the value of one document in the collection. In order to get only the latest element in the collection I use this query:
db.balance.find().sort({date: -1}).limit(1);
There's a column called 'value' and I want to get that.
db.balance.find().sort({date: -1}).limit(1).value; however does not show the data I want. It shows nothing:
What's wrong with it?
find returns a cursor. You'll need to convert it to an array in order to actually extract the value. Try this:
db.balance.find().sort({date: -1}).limit(1).toArray()[0].value;
This is, of course, much easier inside of meteor (either in code or via meteor shell) because you can do:
Balance.findOne({}, {sort: {date: -1}}).value;

MongoDB: $addToSet duplicate result callback in Meteor

There are plenty of $addToSet topics out there, but after an hour of searching I still don't know how to evaluate in meteor-serverside-javascript-code if $addToSet added a new element to an array or it was a duplicate match.
The closest one I found was How to check if Mongo's $addToSet was a duplicate or not, but I don't know how to get a db object within meteor.
As written in other posts, the callback-function as a last parameter of the update method always returns 1 and it's always successful, no matter it's a duplicate or distinct element.
If there is no solution currently, I would like to know if there are other ways of checking a nested array (inside one specific collection) for a specific element. A simple true/false result information would be enough.
EDIT:
Ok, I managed to get the Bulk Update working now with the following lines:
var db = MongoInternals.defaultRemoteCollectionDriver().mongo.db;
var col = db.collection("posts");
var batch = col.initializeOrderedBulkOp();
batch.find({_id: postid}).upsert().updateOne({"$addToSet": ...});
batch.execute(function(err, result) {
if (err) throw err;
console.log("RESULT: ", JSON.stringify(result));
//db.close();
});</code>
The $addToSet works with this implementation, but the result object returned from the execution, still, is always the same:
RESULT: {
"ok":1,
"writeErrors":[],
"writeConcernErrors":[],
"nInserted":0,
"nUpserted":0,
"nMatched":1,
"nModified":null,
"nRemoved":0,
"upserted":[]
}
The interesting value nModified stays null both for an update and (duplicate found) skip.
Any ideas?
If I re-phrase the question, you're trying to figure if what you're about to insert is already there.
Why not simply query the object for it before attempting to insert?
If you have a set (array) you can simply do
db.collection.find({array_key: object_to_find_in_array})
and see if it returns an object or nothing. Then update as necessary.

Categories

Resources