如何查询 CloudCode beforeSave 中的对象?
How to query objects in the CloudCode beforeSave?
我正在尝试使用 CloudCode beforeSave 将 新对象 与 原始 进行比较功能。我需要将 update 中发送的字段与现有值进行比较。问题是我无法正确获取对象。当我 运行 查询时,我总是从发送的对象中获取值。
更新:我尝试了一种不同的方法并且可以获得旧的寄存器(已经保存在解析中的那个)。 但是在请求中发送的新的被旧的覆盖。什么?!另一个问题是,即使代码发送了 response.success()
,更新也没有保存。
我相信我在这里遗漏了一些非常明显的东西。或者我遇到了错误或其他问题...
新方法
Parse.Cloud.beforeSave('Tasks', function(request, response) {
if ( !request.object.isNew() )
{
var Task = Parse.Object.extend("Tasks");
var newTask = request.object;
var oldTask = new Task();
oldTask.set("objectId", request.object.id);
oldTask.fetch()
.then( function( oldTask )
{
console.log(">>>>>> Old Task: " + oldTask.get("name") + " version: " + oldTask.get("version"));
console.log("<<<<<< New Task: " + newTask.get("name") + " version: " + newTask.get("version"));
response.success();
}, function( error ) {
response.error( error.message );
}
);
}
});
OBJ 已发送 {"name":"LLL", "version":333}
日志
I2015-10-02T22:04:07.778Z]v175 before_save triggered for Tasks for user tAQf1nCWuz:
Input: {"original":{"createdAt":"2015-10-02T17:47:34.143Z","name":"GGG","objectId":"VlJdk34b2A","updatedAt":"2015-10-02T21:57:37.765Z","version":111},"update":{"name":"LLL","version":333}}
Result: Update changed to {}
I2015-10-02T22:04:07.969Z]>>>>>> Old Task: GGG version: 111
I2015-10-02T22:04:07.970Z]<<<<<< New Task: GGG version: 111
注意:我正在通过 cURL 和解析控制台测试登录。
CloudCode beforeSave
Parse.Cloud.beforeSave("Tasks", function( request, response) {
var query = new Parse.Query("Tasks");
query.get(request.object.id)
.then(function (oldObj) {
console.log("-------- OLD Task: " + oldObj.get("name") + " v: " + oldObj.get("version"));
console.log("-------- NEW Task: " + request.object.get("name") + " v: " + request.object.get("version"));
}).then(function () {
response.success();
}, function ( error) {
response.error(error.message);
}
);
});
cURL 请求
curl -X PUT \
-H "Content-Type: application/json" \
-H "X-Parse-Application-Id: xxxxx" \
-H "X-Parse-REST-API-Key: xxxxx" \
-H "X-Parse-Session-Token: xxxx" \
-d "{\"name\":\"NEW_VALUE\", \"version\":9999}" \
https://api.parse.com/1/classes/Tasks/VlJdk34b2A
JSON响应
"updatedAt": "2015-10-02T19:45:47.104Z"
日志
日志打印了 original 和 new 值,但我也不知道如何访问它。
I2015-10-02T19:57:08.603Z]v160 before_save triggered for Tasks for user tAQf1nCWuz:
Input: {"original":{"createdAt":"2015-10-02T17:47:34.143Z","name":"OLD_VALUE","objectId":"VlJdk34b2A","updatedAt":"2015-10-02T19:45:47.104Z","version":0},"update":{"name":"NEW_VALUE","version":9999}}
Result: Update changed to {"name":"NEW_VALUE","version":9999}
I2015-10-02T19:57:08.901Z]-------- OLD Task: NEW_VALUE v: 9999
I2015-10-02T19:57:08.902Z]-------- NEW Task: NEW_VALUE v: 9999
无需执行查询,您可以通过检查哪些键是 脏 来查看修改后的属性,这意味着它们已被更改但尚未保存。
JS SDK 包含 dirtyKeys()
,其中 returns 已更改的键。试试这个。
var attributes = request.object.attributes;
var changedAttributes = new Array();
for(var attribute in attributes) {
if(object.dirty(attribute)) {
changedAttributes.push(attribute);
// object.get(attribute) is changed and the key is pushed to the array
}
}
需要说明的是,要获取原始属性的值,您必须调用 get()
来加载这些预保存值。请注意,这将算作另一个 API 请求。
如果我是你,我会将旧值作为参数传递给云函数,以便你可以在 request.params.(参数名称) 下访问它。我不相信还有另一种方法可以获得旧值。一个古老的 SO 问题说您可以使用 .get(),但您声称那不起作用。除非你的版本已经有9999了...
edit - 我想 beforeSave 不像普通函数那样被调用...所以创建一个 "update version" 函数来传递当前任务和您尝试更新到的版本,也许吧?
经过大量测试和错误后,我可以弄清楚发生了什么。
原来 Parse 正在将所有具有相同 class 和 id 的对象合并到一个实例中 。这就是为什么我总是在数据库中注册对象或用户发送的对象。老实说,我无法理解这种行为,但无论如何...
Parse javascript sdk 提供了一种名为 Parse.Object.disableSingeInstance
link 的方法来禁用此 "feature"。但是,一旦调用该方法,所有已定义的对象都是未定义的。这包括发送的对象。 表示您既不能保存已发送的对象供以后参考。
唯一的选择是保存已发送对象的键和值,稍后重新创建。因此,我需要在调用 disableSingleInstance
之前捕获请求,将其转换为 JSON,然后禁用单个实例,获取保存在数据库中的对象并使用保存的 JSON 重新创建发送的对象.
它不漂亮,绝对不是最有效的代码,但我找不到任何其他方法。如果有人有其他方法,一定要告诉我。
Parse.Cloud.beforeSave('Tasks', function(request, response) {
if ( !request.object.isNew() ) {
var id = request.object.id;
var jsonReq;
var Task = Parse.Object.extend("Tasks");
var newTask = new Task;
var oldTask = new Task;
// getting new Obj
var queryNewTask = new Parse.Query(Task);
queryNewTask.get(id)
.then(function (result) {
newTask = result;
// Saving values as a JSON to later reference
jsonReq = result.toJSON();
// Disable the merge of obj w/same class and id
// It will also undefine all Parse objects,
// including the one sent in the request
Parse.Object.disableSingleInstance();
// getting object saved in DB
oldTask.set("objectId", id);
return oldTask.fetch();
}).then(function (result) {
oldTask = result;
// Recreating new Task sent
for ( key in jsonReq ) {
newTask.set( key, jsonReq[key]);
}
// Do your job here
}, function (error) {
response.error( error.message );
}
);
}
});
嘿,这对我来说非常有用:
var dirtyKeys = request.object.dirtyKeys();
var query = new Parse.Query("Question");
var clonedData = null;
query.equalTo("objectId", request.object.id);
query.find().then(function(data){
var clonedPatch = request.object.toJSON();
clonedData = data[0];
clonedData = clonedData.toJSON();
console.log("this is the data : ", clonedData, clonedPatch, dirtyKeys);
response.success();
}).then(null, function(err){
console.log("the error is : ", err);
});
对于那些在 2021 年左右来到此线程的人,如果您在保存之前已将服务器数据加载到客户端 SDK 中,您可以通过传递该服务器来解决此问题save()
函数的 context
选项中来自客户端 SDK 的数据,然后在 beforeSave
afterSave
云函数中使用它。
// eg JS client sdk
const options = {
context: {
before: doc._getServerData() // object data, as loaded
}
}
doc.save(null, options)
// #beforeSave cloud fn
Parse.Cloud.beforeSave(className, async (request) => {
const { before } = request.context
// ... do something with before ...
})
警告:如果您没有在客户端的 _getServerData()
函数中加载属性,这对您没有帮助
第二个警告:parse 不会在您的云函数中为您处理(反)序列化,例如:
{
before: { // < posted as context
status: {
is: 'atRisk',
comment: 'Its all good now!',
at: '2021-04-09T15:39:04.907Z', // string
by: [Object] // pojo
}
},
after: {
status: { // < posted as doc's save data
is: 'atRisk',
comment: 'Its all good now!',
at: 2021-04-09T15:39:04.907Z, // instanceOf Date
by: [ParseUser] // instanceOf ParseUser
}
}
}
我正在尝试使用 CloudCode beforeSave 将 新对象 与 原始 进行比较功能。我需要将 update 中发送的字段与现有值进行比较。问题是我无法正确获取对象。当我 运行 查询时,我总是从发送的对象中获取值。
更新:我尝试了一种不同的方法并且可以获得旧的寄存器(已经保存在解析中的那个)。 但是在请求中发送的新的被旧的覆盖。什么?!另一个问题是,即使代码发送了 response.success()
,更新也没有保存。
我相信我在这里遗漏了一些非常明显的东西。或者我遇到了错误或其他问题...
新方法
Parse.Cloud.beforeSave('Tasks', function(request, response) {
if ( !request.object.isNew() )
{
var Task = Parse.Object.extend("Tasks");
var newTask = request.object;
var oldTask = new Task();
oldTask.set("objectId", request.object.id);
oldTask.fetch()
.then( function( oldTask )
{
console.log(">>>>>> Old Task: " + oldTask.get("name") + " version: " + oldTask.get("version"));
console.log("<<<<<< New Task: " + newTask.get("name") + " version: " + newTask.get("version"));
response.success();
}, function( error ) {
response.error( error.message );
}
);
}
});
OBJ 已发送 {"name":"LLL", "version":333}
日志
I2015-10-02T22:04:07.778Z]v175 before_save triggered for Tasks for user tAQf1nCWuz:
Input: {"original":{"createdAt":"2015-10-02T17:47:34.143Z","name":"GGG","objectId":"VlJdk34b2A","updatedAt":"2015-10-02T21:57:37.765Z","version":111},"update":{"name":"LLL","version":333}}
Result: Update changed to {}
I2015-10-02T22:04:07.969Z]>>>>>> Old Task: GGG version: 111
I2015-10-02T22:04:07.970Z]<<<<<< New Task: GGG version: 111
注意:我正在通过 cURL 和解析控制台测试登录。
CloudCode beforeSave
Parse.Cloud.beforeSave("Tasks", function( request, response) {
var query = new Parse.Query("Tasks");
query.get(request.object.id)
.then(function (oldObj) {
console.log("-------- OLD Task: " + oldObj.get("name") + " v: " + oldObj.get("version"));
console.log("-------- NEW Task: " + request.object.get("name") + " v: " + request.object.get("version"));
}).then(function () {
response.success();
}, function ( error) {
response.error(error.message);
}
);
});
cURL 请求
curl -X PUT \
-H "Content-Type: application/json" \
-H "X-Parse-Application-Id: xxxxx" \
-H "X-Parse-REST-API-Key: xxxxx" \
-H "X-Parse-Session-Token: xxxx" \
-d "{\"name\":\"NEW_VALUE\", \"version\":9999}" \
https://api.parse.com/1/classes/Tasks/VlJdk34b2A
JSON响应
"updatedAt": "2015-10-02T19:45:47.104Z"
日志 日志打印了 original 和 new 值,但我也不知道如何访问它。
I2015-10-02T19:57:08.603Z]v160 before_save triggered for Tasks for user tAQf1nCWuz:
Input: {"original":{"createdAt":"2015-10-02T17:47:34.143Z","name":"OLD_VALUE","objectId":"VlJdk34b2A","updatedAt":"2015-10-02T19:45:47.104Z","version":0},"update":{"name":"NEW_VALUE","version":9999}}
Result: Update changed to {"name":"NEW_VALUE","version":9999}
I2015-10-02T19:57:08.901Z]-------- OLD Task: NEW_VALUE v: 9999
I2015-10-02T19:57:08.902Z]-------- NEW Task: NEW_VALUE v: 9999
无需执行查询,您可以通过检查哪些键是 脏 来查看修改后的属性,这意味着它们已被更改但尚未保存。
JS SDK 包含 dirtyKeys()
,其中 returns 已更改的键。试试这个。
var attributes = request.object.attributes;
var changedAttributes = new Array();
for(var attribute in attributes) {
if(object.dirty(attribute)) {
changedAttributes.push(attribute);
// object.get(attribute) is changed and the key is pushed to the array
}
}
需要说明的是,要获取原始属性的值,您必须调用 get()
来加载这些预保存值。请注意,这将算作另一个 API 请求。
如果我是你,我会将旧值作为参数传递给云函数,以便你可以在 request.params.(参数名称) 下访问它。我不相信还有另一种方法可以获得旧值。一个古老的 SO 问题说您可以使用 .get(),但您声称那不起作用。除非你的版本已经有9999了...
edit - 我想 beforeSave 不像普通函数那样被调用...所以创建一个 "update version" 函数来传递当前任务和您尝试更新到的版本,也许吧?
经过大量测试和错误后,我可以弄清楚发生了什么。
原来 Parse 正在将所有具有相同 class 和 id 的对象合并到一个实例中 。这就是为什么我总是在数据库中注册对象或用户发送的对象。老实说,我无法理解这种行为,但无论如何...
Parse javascript sdk 提供了一种名为 Parse.Object.disableSingeInstance
link 的方法来禁用此 "feature"。但是,一旦调用该方法,所有已定义的对象都是未定义的。这包括发送的对象。 表示您既不能保存已发送的对象供以后参考。
唯一的选择是保存已发送对象的键和值,稍后重新创建。因此,我需要在调用 disableSingleInstance
之前捕获请求,将其转换为 JSON,然后禁用单个实例,获取保存在数据库中的对象并使用保存的 JSON 重新创建发送的对象.
它不漂亮,绝对不是最有效的代码,但我找不到任何其他方法。如果有人有其他方法,一定要告诉我。
Parse.Cloud.beforeSave('Tasks', function(request, response) {
if ( !request.object.isNew() ) {
var id = request.object.id;
var jsonReq;
var Task = Parse.Object.extend("Tasks");
var newTask = new Task;
var oldTask = new Task;
// getting new Obj
var queryNewTask = new Parse.Query(Task);
queryNewTask.get(id)
.then(function (result) {
newTask = result;
// Saving values as a JSON to later reference
jsonReq = result.toJSON();
// Disable the merge of obj w/same class and id
// It will also undefine all Parse objects,
// including the one sent in the request
Parse.Object.disableSingleInstance();
// getting object saved in DB
oldTask.set("objectId", id);
return oldTask.fetch();
}).then(function (result) {
oldTask = result;
// Recreating new Task sent
for ( key in jsonReq ) {
newTask.set( key, jsonReq[key]);
}
// Do your job here
}, function (error) {
response.error( error.message );
}
);
}
});
嘿,这对我来说非常有用:
var dirtyKeys = request.object.dirtyKeys();
var query = new Parse.Query("Question");
var clonedData = null;
query.equalTo("objectId", request.object.id);
query.find().then(function(data){
var clonedPatch = request.object.toJSON();
clonedData = data[0];
clonedData = clonedData.toJSON();
console.log("this is the data : ", clonedData, clonedPatch, dirtyKeys);
response.success();
}).then(null, function(err){
console.log("the error is : ", err);
});
对于那些在 2021 年左右来到此线程的人,如果您在保存之前已将服务器数据加载到客户端 SDK 中,您可以通过传递该服务器来解决此问题save()
函数的 context
选项中来自客户端 SDK 的数据,然后在 beforeSave
afterSave
云函数中使用它。
// eg JS client sdk
const options = {
context: {
before: doc._getServerData() // object data, as loaded
}
}
doc.save(null, options)
// #beforeSave cloud fn
Parse.Cloud.beforeSave(className, async (request) => {
const { before } = request.context
// ... do something with before ...
})
警告:如果您没有在客户端的 _getServerData()
函数中加载属性,这对您没有帮助
第二个警告:parse 不会在您的云函数中为您处理(反)序列化,例如:
{
before: { // < posted as context
status: {
is: 'atRisk',
comment: 'Its all good now!',
at: '2021-04-09T15:39:04.907Z', // string
by: [Object] // pojo
}
},
after: {
status: { // < posted as doc's save data
is: 'atRisk',
comment: 'Its all good now!',
at: 2021-04-09T15:39:04.907Z, // instanceOf Date
by: [ParseUser] // instanceOf ParseUser
}
}
}