How to remove a property from document - mongo / loopback - javascript

I have an old property on one of my models, and I'd like to remove it from all the documents in a collection. I've tried posting via /upsertWithWhere using the id to update by:
passing in undefined for the value which results in "http error 400 bad request"
passing in null which just sets the property to null
I also was thinking I could do a regular POST and just overwrite each document, but these particular documents are large and I'd rather not do that.
Is there a way to simply patch it?
Edit: Need an answer that implements this Via the Loopback API.

This query should do the trick:
db.collection('collection_name').update({},{$unset: {"old_property": ""}}, {multi:true})
Obviously, just make sure you insert into "old_property" the field name of that old property.
Explaining the query a little further...
"{}" matches all documents in the collection
"{$unset: {"old_property": ""}" removes the field(s) specified
"{multi:true}" (An optional field for update) Allows you to update multiple documents when set to true
Used this as a reference: https://docs.mongodb.com/manual/reference/method/db.collection.update/#multi-parameter

Related

Firestore says I have inequality filter on multiple properties, when I don't

I am trying to do a "small hack" to avoid reading the User document everytime the page loads. So I save it locally, everytime the page loads I get the local version, get the updated_at property and then do something like WHERE last_updated > {{updated_at}}. For that, I want to use this:
firebase.firestore().collection('User')
.where(firebase.firestore.FieldPath.documentId(), '==', firebase.auth().currentUser.uid)
.where('updated_at', '>', updated_at)
.get()
As you can see, I have one equality (==) and one inequality (>). Why do I get the following error on the console:
FirebaseError: Cannot have inequality filters on multiple properties: updated_at
at new t (https://www.gstatic.com/firebasejs/6.0.2/firebase-firestore.js:1:47054)
at t.fromRpcStatus (https://www.gstatic.com/firebasejs/6.0.2/firebase-firestore.js:1:116660)
at t.fromWatchChange (https://www.gstatic.com/firebasejs/6.0.2/firebase-firestore.js:1:125914)
at t.onMessage (https://www.gstatic.com/firebasejs/6.0.2/firebase-firestore.js:1:242411)
at https://www.gstatic.com/firebasejs/6.0.2/firebase-firestore.js:1:241212
at https://www.gstatic.com/firebasejs/6.0.2/firebase-firestore.js:1:241997
at https://www.gstatic.com/firebasejs/6.0.2/firebase-firestore.js:1:144869
I am doing this to try to avoid reading from the database if the local version is the same as the one in the database. Maybe if you have a better way, please let me know.
Thanks
firebaser here
The equality check you have on documentId() is internally converted into a range check by Firestore, because the keys are stored as the last items in existing indexes (if I understand correctly). And that means that server-side you're trying to perform two inequality/range checks, which isn't allowed.
So the behavior you are seeing is correct. But it's definitely not intuitive, and the error message is also not helpful. We'll look for a way to improve the error message by detecting this combination.
I had the same problem and I implemented the following hack: I added the id as part of the field name on which I made the check for the latest version. If your logic allows you to do that, for you this would mean:
firebase.firestore().collection('User')
.where(id + '_updated_at', '>', updated_at)
.get()
This allows to bundle in just one where statement both the check on the id and on the date (documents with different ids wont have the field id + '_updated_at' and wont therefore be selected).
Worked like a charm for me

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 delete an attribute when sending a partial object update to Algolia?

I need to use partialUpdateObject from the Algolia Javascript SDK to delete an attribute from an object that is already in the index.
My scenario is that I have a description field on my object that is optional. If the user originally sets a description and then later deletes it, I want to remove the description altogether from the object.
I do not want to overwrite the whole object (without the description attribute) because I have some count attributes on the object that I do not want to have to recalculate.
As far as I can tell in the documentation there isn't a way to do it and my workaround is to set the description as an empty string. Is that the recommended approach?
You're right: you cannot totally remove the attribute from an object with a partialUpdateObject operation. As a work-around you can set it to null, maybe that's enough for your use-case?
If you really want to delete the field you can :
Get your object with the search function
Store all fields values
Update (not partial update) your object without passing the field you want to delete

Backbone datatypes - type casting?

It just took me over an hour to find out that a Backbone query on a collection was failing because I queried the wrong data type.
So this query failed because I used the wrong data type for id:
element = collection.findWhere({id: "123", att: true});
This one worked and returned a model from the collection.
element = collection.findWhere({id: 123, att: true});
The reason was that I took the id from a DOM element.
I am interfacing a lot with the DOM in my application.
Is there an option in Backbone that would allow me to make it more lenient in regards to data types?
One option is to override your models parse method and so a toString on the id coming in. Then you'll have strings from the dom and in your model.
http://backbonejs.org/#Model-parse
Personally I'd prefer to explicitly cast my queries instead using parseInt but they're both options

How can I get the key as well as the value when using db.js to query IndexedDB?

I have an IndexedDB of changes. I add an item like this, and then log the result to check the key has been created successfully:
_this._idb.add('steps', step).done(function (items) {
var item = items[0];
_logger.log("ADDED STEP", { id: item.__id__, step: item }, "CT");
});
The output from this is as expected:
...as you can see, the id has been added to the object when it is stored.
However, when I query the db to getback a list of objects, using this code:
this._idb.steps.query('timestamp').bound(start, end).execute().done(function (results) {
_logger.log("Results", results, "CT");
}
I don't get the id as part of the object that is returned:
... and the lack of id makes updating and deleting impossible.
How can I get the id of the item when I query indexed db using db.js - or am I approaching this in the wrong way, and is there something else I should be doing?
(Note: I'm using TypeScript to compile the JS, but I don't think that's especially relevant to this question)
This is expected behaviour, you're only going to get the __id__ property if you don't define a keyPath in your db schema.
Because there's no keyPath defined the value is not associated with it in indexeddb, it's only added to the resulting object after it has been added, because at that point in time we know the auto-incremented value that IndexedDB has assigned to it.
Since the value isn't really part of the object I don't have any way to assign it to the object when it comes out during a query, maybe I could use the position in the array but that's more likely to be wrong than right.
If you want the ID to be persisted against the object then you need to define a keyPath as part of the object store schema and the property will be added to the resulting object and available and it will be on the object returned from a query.
Disclaimer - I wrote db.js
Looking at the source, __id__ is only defined when your keyPath is null in the add() method. From what I'm seeing, you'll never see this in a query() response.
In IDB null keyPaths are allowed only when using auto-incrementing ("out-of-line") keys. So if you're getting the object back, it should have an auto-incrementing key on it or some other keyPath.
The __ prefix in JavaScript usually means the developer intended it to be a "private" property. I'm guessing this is for internal use and you shouldn't be counting on this in your application code.
Consider using explicit, so-called "in-line" keys on your object store.
The goal of db.js is easy and simple to use. Your is advanced use case.

Categories

Resources