Backbone findWhere finds nothing [duplicate] - javascript

This question already has answers here:
How do I get a model from a Backbone.js collection by its id?
(2 answers)
Closed 6 years ago.
My collection has 4494 models. I try to use findWhere to get specific model by id. The findWhere returns 'undefined'.
It works ok if I limit the number of models. The strangeness heppens when the number of models is over 100.
var users = this.usersCollection;
console.log(users);
console.log(users.findWhere({uid: 1}));

While the problem is solved (using findWhere before the collection is actually fetched) thanks to TJ's comment, you might want to use .get instead of findWhere when searching a model by id.
If your User model looks something like this:
var User = Backbone.Model.extend({
idAttribute: 'uid',
// ...
});
You could get a user by id from the collection directly:
var user = users.get(1);
You can also use get with the model's cid or the model instance.
user === users.get(user.cid)
user === users.get(user)
This is better because Backbone keeps a hash of the models with the specified id attribute as the key in addition of the usual array.

The problem was that I tried to use my collection before it was completely fetched.

Related

Set property in mongoose object after query [duplicate]

This question already has answers here:
Why can't you modify the data returned by a Mongoose Query (ex: findById)
(3 answers)
Closed 3 years ago.
while development of an API, I often need to set extra properties in the result of mongoDb query results. But I can't do it in a good way. For example
Model
const Cat = mongoose.model('Cat', { name: String,age:Number });
Query
Cat.findOne({age:2}) .then(
cat=>{
cat.breed="puppy";
console.log(cat)
} )
here after I get the result from mongoDb I want to set the property of breed to the result , but I can't do it because the property is not defined in the Schema
So to set an extra property I use a hack
cat = JSON.parse(JSON.stringify(cat));
cat.favFood = "Milk"
I don't think its a good way to code. please give a better way of setting property and explain how the hack is working.
Mongoose can actually do the conversion toObject for you with the .lean() option. This is preferred over manual conversion after the query (as willis mentioned) because it optimizes the mongoose query by skipping all the conversion of the raw Mongo document coming from the DB to the Mongoose object, leaving the document as a plain Javascript object. So your query will look something similar to this:
Cat.findOne({age:2}).lean().then(
cat=>{
cat.breed="puppy";
console.log(cat)
}
)
The result will be the same except that this will skip the Mongoose document-to-object conversion middleware. However, note that when you use .lean() you lose all the Mongoose document class methods like .save() or .remove(), so if you need to use any of those after the query, you will need to follow willis answer.
Rather than using JSON.parse and JSON.stringify, you can call toObject to convert cat into a regular javascript object.
Mongoose objects have methods like save and set on them that allow you to easily modify and update the corresponding document in the database. Because of that, they try to disallow adding non-schema properties.
Alternatively, if you are trying to save these values you to the database, you may wish to look into the strict option (which is true by default).

How to add auto increment to existing collection in mongodb/node.js?

Is there any methods or packages, that can help me add auto increments to existing collection? Internet full of information, about how to add AI before you create collection, but I did not find information on how to add AI when collection already exist...
MongoDB does not have an inbuilt auto-increment functionality.
Create a new collection to keep track of the last sequence value used for insertion:
db.createCollection("counter")
It will hold only one record as:
db.counter.insert({_id:"mySequence",seq_val:0})
Create a JavaScript function as:
function getNextSequenceVal(seq_id){
// find record with id seq_id and update the seq_val by +1
var sequenceDoc = db.counter.findAndModify({
query:{_id: seq_id},
update: {$inc:{seq_val:1}},
new:true
});
return sequenceDoc.seq_val;
}
To update all the already existing values in your existing collection, this should work (For the empty {}, you can place your conditions if you want to update some documents only):
db.myCollection.update({},
{$set:{'_id':getNextSequenceVal("mySequence")}},{multi:true})
Now you can insert new records into your existing collection as:
db.myCollection.insert({
"_id":getNextSequenceVal("mySequence"),
"name":"ABC"
})
MongoDB reserves the _id field in the top level of all documents as a primary key. _id must be unique, and always has an index with a unique constraint. It is an auto-incrementing field. However, it is possible to define your own auto-incrementing field following the tutorial in the MongoDB documentation.
Tutorial link: https://docs.mongodb.com/v3.0/tutorial/create-an-auto-incrementing-field/

Passing variable into Backbone.where [duplicate]

This question already has an answer here:
Trouble referencing variable in Collections.where method within render function
(1 answer)
Closed 7 years ago.
I want to form a collection from a JSON based on the obtained value and Backbone's where seemed like a perfect tool, but it looks like it doesn't accept variables. Is it possible to achieve this sort of functionality using some of Backbone, Lodash or Underscore methods?
### collection instantiated above
App.vent.on 'event', (obtained_value) ->
desired_models = collection.where(attribute: obtained_value)
console.log desired_models
### outputs empty array
>[]
It does work when I pass key: value directly, but I need to form collection dynamically. Maybe I've initially taken a false route and the solution is in the another direction?
I'm assuming your goal is to vary the attribute you're searching for, since if the value is varied, object literals should work fine.
You can do it, just not with an object literal inline. Here's how I would do it in JavaScript:
App.vent.on('event', function (obtainedValue) {
var finder = {};
finder[attribute] = obtainedValue;
desiredModels = collection.where(finder);
console.log(desiredModels);
});
that wont work, you need to pass an object so it would be like this
collection.where({attribute: obtained_value});
in coffescript you can do the following
attribute_var=
attribute:obtained_value
collection.where(attribute_var);
best regards

Updating a subfield in a mongoDB document using findOne and save

I'm trying to update a particular subfield in a mongoDB document and have decided to first find the object in question and then save an updated one. For some reason, the save option seems to ignore my changes.
I have one object in my collection, and it meets the following schema:
var tschema= mongoose.Schema({
a: Object
})
var t = db.model('tongoose',tschema);
t.findOne({},function(err,obj){
console.log(obj.a); //yields ['banana',3]
obj.a[1]=1; //to make ['banana',1]
console.log(obj); //yields ['banana',1]
obj.save(function(err,real){
console.log(real); //yields ['banana',1]
});
});
But when I go back to the mongoDB and look up the saved object, it never shows any changes. Can you spot what I'm doing wrong?
Much appreciated.
Because your schema defines a as a generic object, that field is treated as the Mixed type by Mongoose and you need to mark it as changed by calling markModified or save will ignore the change.
obj.markModified('a');
obj.save(function(err,real){ ...
See the discussion of Mixed types on this page of the docs.

How does map work with a Backbone collection?

Goal: I am trying to create a case insensitive search that goes through my collection and tries to match the user query against model's name attribute. Right now if I want to find a specific model, the search query must be exact.
It seems there is no easy way to do something so simple in Backbone, not out of the box. The function map came to mind. What if I could go through the entire collection and change model's name attribute to lower case, then change user query to lower case as well and voila!
But the problem is I have no idea how to use Backbone Collection and map function. There is no documentation on map in Backbone docs, other than a link that leads you to underscore documentation with a super primitive example code using an array of three numbers.
This does not work...why?
this.collection.map(function(model) {
return model.get('name').toLowerCase();
});
Actually, all of underscore's collection methods are proxied on Backbone.Collection objects. when you do a collection.map(... it returns an array of objects returned by the mapped function. The solution presented by raina77ow does not work since a Backbone.Collection is not an array and assigning the result of the map to this.collection will destroy the collection itself.
If you want to filter a collection, I would recommend using the filter method. ( I assume you are working from a Backbone.View:
var filter = this.$('#search-field').val(),
filteredModels = this.collection.filter( function( model ) {
return model.get('name').toLowerCase() === filter;
};
this.collection.reset( filteredModels );
Note that any of underscore's proxied methods on collections will return an array of models. If you then want to use them, you can reset the collection with these models or, equivalently, set the collection's models attribute to the filtered results: this.collection.models = filteredModels. The first form has the advantage of triggering a reset event on the collection to which you can listen to and, for example re-render your view.

Categories

Resources