javascript - 获取带有查询和匹配项目的项目给有收藏项目的用户

时间:2014-09-01 22:06:59

标签: javascript push-notification parse-platform cloud

我正在使用parse.com的javascript云代码SDK编写脚本。以下是我在parse.com帐户中保存的信息以及我正在尝试使用的信息。

我在一个名为TestItem的解析类中保存了一堆项目,这些项目有一个objectId,项目名称,用餐时间(午餐,晚餐)以及列的位置。我还有一个名为UserFavourites的课程。在此类中,对象具有objectId,项目名称和指向将项目保存为收藏夹的用户的指针。

有了这些信息,我试图用javascript编写一个云代码脚本。这将使项目与用户喜欢的项目相匹配,并向他们发送推送通知,说明项目的位置和内容以及项目的位置。我有一些代码可以做到这一点,但是这段代码会为每个项目发送一个不同的通知,这可能会让用户讨厌这个代码。

Parse.Cloud.define("push", function(request, response) {

var TestItem = Parse.Object.extend("TestItem");
var query = new Parse.Query(TestItem);
query.limit(1000);
query.equalTo('school', 'Union College (NY)');
query.find({
    success: function(resultsItem) {
        //console.log("Successfully retrieved " + resultsItem.length + " :1111.");
        for (var i = 0; i < resultsItem.length; i++) { 
            var object = resultsItem[i];
            var item = object.get('item');
            var school = object.get('school');
            var meal = object.get('meal');
            var meal = meal.toLowerCase();
            var diningLocation = object.get('schoolMenu');

            //var itemArray = [];
            var UserFavourite = Parse.Object.extend("UserFavourite");
            var queryFavourite = new Parse.Query(UserFavourite);
            queryFavourite.limit(1000);
            queryFavourite.equalTo("item", item)
            queryFavourite.equalTo("school", school)
            queryFavourite.find({
                success: function(results) {

                    for (var i = 0; i < results.length; i++) { 
                        var objectFav = results[i];
                        var user = objectFav.get('user');
                        var userID = user.id;
                        var realItem = objectFav.get('item');
                        console.log(objectFav.get('user'));
                        console.log(objectFav.get('item'));

                        var UserClass = Parse.Object.extend("User");
                        var queryUser = new Parse.Query(UserClass);
                        queryUser.get(userID, {
                          success: function(userResult) {
                            console.log(userResult.get('school'));        
                            console.log('install:' + userResult.get('installation').id);
                            var userInstallationId = userResult.get('installation').id;
                            var queryInstallation = new Parse.Query(Parse.Installation);
                            queryInstallation.equalTo('objectId', userInstallationId);
                            queryInstallation.find({
                                success: function(results) {
                                    console.log('number' + results.length); 

                                        Parse.Push.send({
                                        // deviceType: [ "ios" ],
                                            where: queryInstallation,
                                            data: {
                                                alert: realItem + " is being served at " + diningLocation + " for " + meal
                                            }
                                        }, 
                                        {
                                            success: function() {
                                            // Push was successful
                                            },
                                            error: function(error) {
                                            // Handle error
                                            }
                                        }); 
                                },
                                error: function(error) {
                                    console.log('error');
                                }
                              });
                          },
                          error: function(error) {
                            console.log('error');
                          }
                        });
                     }  
                },
                error: function(error) {
                    alert("Error: " + error.code + " " + error.message);
                }
            });
         }    
    },
    error: function(error) {
        alert("Error: " + error.code + " " + error.message);
    }
});  
});

正如你所看到的那样它很长而且看起来不太好看,我试图将项目保存到一个数组中,以避免发送两个或更多通知,但无法使其工作。

所以我开始编写另一个使用看起来更好的承诺的脚本,但现在还没有得到它,它可以将项目与有优势项目的用户匹配并放置objectId&#39; s数组中的那些用户。这是代码。

Parse.Cloud.define("test", function(request, response) {

var UserFavourite = Parse.Object.extend("UserFavourite");
var queryFavourite = new Parse.Query(UserFavourite);

var userArray = [];
var TestItem = Parse.Object.extend("TestItem");
var query = new Parse.Query(TestItem);
query.limit(1000);
query.equalTo('school', 'Union College (NY)');
query.find().then(function(results) {
    return results;


}).then(function(results) {
    var promises = [];
    for (var i = 0; i < results.length; i++) { 
        var object = results[i];
        var item = object.get('item');
        var school = object.get('school');
        var meal = object.get('meal');

        var UserFavourite = Parse.Object.extend("UserFavourite");
        var queryUser = new Parse.Query(UserFavourite);
        queryUser.equalTo("item", item);
        queryUser.equalTo("school", school);
        var prom = queryUser.find().then(function(users) {
            for (var i = 0; i < users.length; i++) {
                var user = users[i];
                var userID = user.get('user').id;
                if (userArray.indexOf(userID) === -1) {
                    userArray.push(userID);
                }
            }
            return userArray;


        });

        promises.push(prom);           
    }   
    return Parse.Promise.when.apply(Parse.Promise, promises);   

}).then(function(results) {
    console.log(userArray);
});
});

但现在有了这段代码,我不知道该去哪里,我认为使用承诺,这是正确的方法,但我现在感到困惑,因为我有所有的用户有一个项目有利于什么那么,我需要得到那些受欢迎且在TestItem类中可用的项目,这是我正在努力的地方。

这是我的UserFavourite类的图片,它有一个指向用户喜欢该项目的用户的指针,并且用户也有多个收藏夹。

enter image description here

提前感谢大家的帮助。

这是你的代码,我改变了一些事情。

Parse.Cloud.define("getAllFavoriteItems", function (request, response) {
var TestItems = Parse.Object.extend("TestItems");
var UserFavorites = Parse.Object.extend("UserFavorites");

var testItemsQuery = new Parse.Query(TestItems);
var userFavoritesQuery = new Parse.Query(UserFavorites);

testItemsQuery.equalTo('school', 'Union College (NY)');

userFavoritesQuery.include('testItems'); //This makes sure to pull all of the favorite item data instead of just the pointer object
userFavoritesQuery.matchesQuery('testItem', testItemsQuery); //This will run this second query against the TestItems
userFavoritesQuery.limit(1000); //limit results to 1000
userFavoritesQuery.ascending('userId'); //group the user id's together in your array

userFavoritesQuery.find({
        success:function(results) {
            var pushNotificationMessage = "";
            var userId = "";
            for (var i=0; i <results.length; i++) {
                if (results[i].get('userId') != userId) { 
                    if (results[i].get('userId') != "") { 
                        //TODO send push notification
                    }
                    userId = results[i].get('userId');
                    pushNotificationMessage = ""; //start a new push notification
                }

                pushNotificationMessage += results[i].get('item').get('name') + ": " + results[i].get('item').get('location') + "\n";

                //SOMEWHERE BEFORE HERE I NEED THE INSTALLATION ID OF THE USER
                //TO SEND THE PUSH TO THAT USER
                Parse.Push.send({
                // deviceType: [ "ios" ],
                    where: queryInstallation,
                    data: {
                        alert: pushNotificationMessage
                    }
                }, 
                {
                    success: function() {
                    // Push was successful
                    },
                    error: function(error) {
                    // Handle error
                    }
                });
            }
            response.success(true);
        },
        error:function(error) {
                response.error();
        }
})
});

可能会为每个用户创建推送的一些代码,粗略轮廓

if (i > 0) {
          if (results[i].get('user') === results[i-1].get('user')) {
            userItems.push(results[i]);
          }
          else {
            userItems.length = 0;
          }

      }
      else {
        userItems.push(results[i]);
      }

如果您了解我要做的事情,请务必告诉我......

因此,用户有两个受欢迎的项目我希望将其分组为一个短语,说明这两个项目的服务内容和位置

这是发送推送的代码

Parse.Push.send({
                    // deviceType: [ "ios" ],
                        where: queryInstallation,
                        data: {
                            alert: pushNotificationMessage
                        }
                    }, 
                    {
                        success: function() {
                        // Push was successful
                        },
                        error: function(error) {
                        // Handle error
                        }
                    });

也可以使用then / promises,

完成

enter image description here

2 个答案:

答案 0 :(得分:6)

我同意@Maxwell你的UserFavorite应该有User和TestItem的链接。这使得您的云功能变得如此简单:

Parse.Cloud.define("getAllFavoriteItems", function(request, response) {

    var TestItem = Parse.Object.extend("TestItem");
    var UserFavorites = Parse.Object.extend("UserFavorites");   
    var testItemsQuery = new Parse.Query(TestItem);
    var userFavoritesQuery = new Parse.Query(UserFavorites);

    testItemsQuery.equalTo('school', request.params.school);

    userFavoritesQuery.include('testItem'); 
    userFavoritesQuery.include('user'); 
    userFavoritesQuery.matchesQuery('testItem', testItemsQuery); //This will run this second query against the TestItems
    userFavoritesQuery.find().then(function(results) {
        var alerts = {};
        for(var i =0 ; i<results.length; i++ ){
            var user = results[i].get('user');
            var testItem = results[i].get('testItem');
            if(user && testItem){
                var instId = user.get('installationId');
                if(!alerts[instId]) {
                    alerts[instId] = [];
                }
                var m = results[i].get('item') + " is being served at {{diningLocation}} for " + testItem.get('meal');
              alerts[instId].push(m);
            }
        }
        response.success(alerts);
    }, function(error) {
        response.error();
    });
});

这是您可以在my github repo中找到的有效代码。 您还可以查看工作演示here

这个想法与Maxwell的回答相同:将UserFavorites类中的链接同时包含User(其中包含installationId)和TestItem个实体。我通过在查询中包含usertestItems属性来让它工作,所以当返回按学校名称过滤的结果时,我已经有了一个installationIds列表。 这是我的架构:

用户 User Schema

<强> TestItem TestItemSchema

<强> UserFavorites UserFavorites

更新

在此代码中,我添加了推送通知:

Parse.Cloud.define("getAllFavoriteItems", function(request, response) {

    var TestItem = Parse.Object.extend("TestItem");
    var UserFavorites = Parse.Object.extend("UserFavorites");   
    var testItemsQuery = new Parse.Query(TestItem);
    var userFavoritesQuery = new Parse.Query(UserFavorites);

    testItemsQuery.equalTo('school', request.params.school);

    function SendPush(installationId, msg) {

        var query = new Parse.Query(Parse.Installation);
        query.equalTo('objectId', installationId);

        Parse.Push.send({
          where: query,
          data: {alert: msg}
        });
    } 

    userFavoritesQuery.include('testItem'); 
    userFavoritesQuery.include('user'); 
    userFavoritesQuery.matchesQuery('testItem', testItemsQuery); //This will run this second query against the TestItems
    userFavoritesQuery.find().then(function(results) {
        var groupedAlerts = {};
        // manually iterating though results to get alert strings ang group by user in groupedAlerts[installationId]
        for(var i =0 ; i<results.length; i++ ){
            var user = results[i].get('user');
            var testItem = results[i].get('testItem');
            if(user && testItem){
                var instId = user.get('installationId');
                if(!groupedAlerts[instId]) {
                    groupedAlerts[instId] = [];
                }
                var m = results[i].get('item') + " is being served at {{dining Location}} for " + testItem.get('meal');
              groupedAlerts[instId].push(m);
            }
        }
        // reformat to array and send push notifications
        var alerts = [];
        for(var key in groupedAlerts) {
            alerts.push({
                installationId: key,
                alerts: groupedAlerts[key],
            });
            // Send push notifications
            SendPush(key, groupedAlerts[key].join());
        }
        response.success(alerts);
    }, function(error) {
        response.error();
    });
});

我还更新了测试数据in live demo(只需按Get Alerts)或随意使用测试数据即可更改云代码响应。 gitnub repo也是最新的。

答案 1 :(得分:2)

这是基于我所理解的您正在尝试解决的问题。如果它没有解决正确的问题,请告诉我,我会看到我能做些什么。

首先查看您的数据库模型,我们可以通过修改UserFavorites表来简化这一点。从最初的两个类开始,您有一个项目表和一个用户表。由于用户可以喜欢许多项目并且项目可以被许多用户所青睐,因此我们存在多对多关系。当发生这种情况时,我们需要创建一个指向其他两个类中的每个类的第三个类。这是UserFavorites表发挥作用的地方。在Parse术语中,UserFavorites表需要有两个指针:一个用于用户,一个用于项目。

enter image description here

一旦UserFavorite表存在它的两个指针,我们可以相当容易地做一些事情。在您的情况下,我们有一些搜索条件:

  1. 每个项目必须在某个学校
  2. 您想限制对前1000的回复
  3. 要完成此任务,您可以通过调用matchesQuery将两个查询合并为一个。

    Parse.Cloud.define("getAllFavoriteItems", function (request, response) {
        var TestItems = Parse.Object.extend("TestItems");
        var UserFavorites = Parse.Object.extend("UserFavorites");
    
        var testItemsQuery = new Parse.Query(TestItems);
        var userQuery = new Parse.Query(Parse.User);
        var userFavoritesQuery = new Parse.Query(UserFavorites);
    
        testItemsQuery.equalTo('school', 'Union College (NY)');
        userQuery.include('Installation');
    
        userFavoritesQuery.include('testItems'); //This makes sure to pull all of the favorite item data instead of just the pointer object
        userFavoritesQuery.include('User'); //This makes sure to pull all of the favorite item data instead of just the pointer object
        userFavoritesQuery.matchesQuery('testItem', testItemsQuery); //This will run this second query against the TestItems
        userFavoritesQuery.matchesQuery('user', userQuery); //This will run the third query against Users, bringing the installation data along with it
        userFavoritesQuery.limit(1000); //limit results to 1000
        userFavoritesQuery.ascending('userId'); //group the user id's together in your array
    
        userFavoritesQuery.find({
                success:function(results) {
                        ...
                },
                error:function(error) {
                        response.error();
                }
        })
    })
    

    一旦我们走得那么远,那么为每个用户编译推送消息应该是直接字符串解析逻辑的问题。例如,在success函数中,我们可以通过以下方式提取数据:

    success:function(results) {
        var pushNotificationMessage = "";
        var userId = "";
        for (var i=0; i <results.length; i++) {
                if (results[i].get('userId') != userId) { 
                    if (results[i].get('userId') != "") { 
                        //TODO send push notification
                    }
                    userId = results[i].get('userId');
                    pushNotificationMessage = ""; //start a new push notification
                }
                pushNotificationMessage += results[i].get('item').get('name') + ": " + results[i].get('item').get('location') + "\n";
        }
        response.success(true);
    }
    

    我还没有对这些示例进行测试,看看它们是否有效,但我希望这可以让您了解如何将查询简化为更易于管理的内容。