SoftInstigate / restheart

Rapid API Development with MongoDB
https://restheart.org
GNU Affero General Public License v3.0
805 stars 171 forks source link

Need to add a new field to an existing document #90

Closed hemraj-sharma closed 8 years ago

hemraj-sharma commented 8 years ago

Hi, Firstly I really want to thank you for your consistent support. I need to add a new field to an existing document. Regards, Hemraj

ujibang commented 8 years ago

Hi @hemraj-sharma

you can use PATCH verb. It modifies the document with passed data and you can use the dot notation with it, example

PATCH /db/coll/doc {"a.b": 1}

will upsert (update or add if not existing) the b property to the a object in doc,

hemraj-sharma commented 8 years ago

Thanks for your reply.

hemraj-sharma commented 8 years ago

Hi ujibang, Can we use the PATCH verb for the $pull functionality. I was trying to use Patch with the body as: -------------->>>> { $pull:{addresses:{$elemMatch:{name:"user1"}}} } <<<<<<<<<<<<<<<<<---------- but getting error as: --------------------->>>>>>>>>>>>>> "rh:exception": [ { "exception": "com.mongodb.MongoCommandException", "exception message": "Command failed with error 52: 'exception: The dollar ($) prefixed field '$pull' in '$pull' is not valid for storage.' on server <<<<<<<<<<<<<<------------ What is the way to pull a sub document from the array of the documents. Thanks a lot. Hemraj

ujibang commented 8 years ago

you can't use $pull. you need to patch the whole array removing the item

we have this in our roadmap but still not implemented https://softinstigate.atlassian.net/browse/RH-19

also for more information refer to this question https://github.com/SoftInstigate/restheart/issues/84

ujibang commented 8 years ago

@hemraj-sharma

just to inform that we just added support to update operators.

currently in master branch, will be in next 1.2 release

Dev-Dipesh commented 7 years ago

@ujibang I want to update specific object in an array for which I have ObjectId.

As per monog db doc:

db.collection.update(
   { <array>: value ... },
   { <update operator>: { "<array>.$" : value } }
)

I'm using npm request for this:

const options = {
  url: `http://domain/SchedulerMVP/vehicles/?filter={'vehicles._id':{$oid: '${vehId}'}}`,
  headers: {
    'connection': 'keep-alive'
  },
  'auth': {
    'user': '...',
    'pass': '...',
    'sendImmediately': false
  },
  body: { sqlVehicleId: { "vehicles.$" : ' 3112' } }, // This is the field I want to add or update to vehicles array object
  json: true,
};

request.patch(options, (err, httpResponse, body) => {
  if (err) {
    console.log(httpResponse, err);
  }
  console.log(JSON.stringify(body, null, 2));
});

Any suggestions how can I achieve it in RESTHeart?

Thanks

ujibang commented 7 years ago

Hi @hemraj-sharma

in order to use the $ positional update operator you need to specify a query via filter query parameter in a bulk update request.

PATCH /db/coll/*?filter={"_id":<docid>,"array": <value>} { "<array>.$" : value }

In order to make this request somehow easier we are going to implement improvement https://softinstigate.atlassian.net/browse/RH-246, so that you'll be able to do

PATCH /db/coll/docid?filter={"array": <value>} { "<array>.$" : value }
Dev-Dipesh commented 7 years ago

@ujibang you mean @Dev-Dipesh 😄, never mind thanks for responding though, that definitely makes it easier in one step, I had to implement in this way while I was waiting:

module.exports = {
  updateSlVehicle: (slVehId, VEH_NO) => {
    return new Promise((resolve, reject) => {
      const options = {
        url: `http://${process.env.REST_HOST}/${process.env.DB}/vehicles/?filter={'vehicles._id':{$oid:'${slVehId}'}}&np`,
        'auth': {
          'user': `${process.env.AUTH_USER}`,
          'pass': `${process.env.AUTH_PASS}`,
          'sendImmediately': false
        }
      };
      request.get(options, (err, httpResponse, body) => {
        if (err) {
          console.log(httpResponse, err);
          reject(err);
        } else {
          const veh = JSON.parse(body);
          index = veh[0].vehicles.findIndex(vehicle => vehicle._id['$oid'] === '${slVehId}');
          veh[0].vehicles[index].sqlVehicleId = VEH_NO;
          request.put({
            url: `http://${process.env.REST_HOST}/${process.env.DB}/vehicles/${veh[0]._id['$oid']}`,
            'auth': {
              'user': `${process.env.AUTH_USER}`,
              'pass': `${process.env.AUTH_PASS}`,
              'sendImmediately': false
            },
            body: veh[0],
            json: true
          }, (err, httpResponse, body) => {
            if (err) {
              reject(err);
            } else {
              resolve('Vehicle updated!');
            }
          });
        }
      });
    });
  }
};
ujibang commented 7 years ago

fyi I just pushed an update that implements the improvement https://softinstigate.atlassian.net/browse/RH-246