بازیابی اشیاء - Backtory.Query

پیش‌نیازها

  1. در صورتی که با سرویس پایگاه‌داده آشنایی ندارید، به معرفی سرویس پایگاه‌داده مراجعه کنید.
  2. در صورتی که هنوز در پنل توسعه‌دهنده خود تنظیمات لازم برای سرویس پایگاه‌داده خود را انجام نداده‌اید، به تنظیمات پنل مراجعه کنید.
  3. در صورتی که ایده‌ای راجع به سرویس Cloud Code ندارید، به معرفی سرویس رایانش مراجعه کنید.
  4. در صورتی که هنوز با SDK سرویس رایانش برای اتصال به سایر سرویس ها آشنایی ندارید یا آن را راه اندازی نکرده اید، به راه اندازی SDK سرویس رایانش مراجعه کنید.

بازیابی ساده

ما تا به این جای کار دیدیم که با دستور fetch‌ می‌توان یک عدد Backtory.Object را از سرور دریافت کرد. روش دیگر استفاده از Backtory.Query می‌باشد که با استفاده از آن می‌توانید لیستی از اشیاء را یک جا بازیابی کنید، برای اشیایی که می‌خواهید بازیابی کنید شرایطی مشخص کنید و …

در بسیاری از حالت دستور fetch به اندازه کافی قدرتمند نیست و کار شما را راه نمی اندازد. Backtory.Query‌ در این شرایط به شما کمک می‌کند تا لیستی از اشیاء را آن طور خودتان می‌خواهید بازیابی کنید.

روش کلی بدین صورت است که یک شی از Backtory.Query بسازید. شرط هایی را بر روی آن تعریف کنید و با استفاده از دستور find لیستی از اشیاء را بازیابی کنید. برای مثال فرض کنید می‌خواهید که GameScore هایی که به نام یک بازیکن خاص ثبت شده است را بازیابی کنید. برای این کار می‌توانید از متود equalTo به شیوه زیر استفاده کنید:

var GameScore = Backtory.Object.extend("GameScore");
var query = new Backtory.Query(GameScore);
query.equalTo("playerName", "Dan Stemkoski");
query.find({
    success: function(results) {
        context.log("Successfully retrieved " + results.length + " scores.");
        // Do something with the returned Backtory.Object values
        for (var i = 0; i < results.length; i++) {
            var object = results[i];
            context.log(object.get("_id") + ' - ' + object.get('playerName'));
        }
    },
    error: function(error) {
        context.log("Error: " + error);
    }
});

تعریف شرط بر روی کوئری

شما به شیوه‌های متفاوتی می‌توانید اشیایی که می‌خواهید بازیابی کنید را فیلتر کنید. یک روش استفاده از متود notEqualTo به شیوه زیر می باشد:

query.notEqualTo("playerName", "Michael Yabuti");

شما می‌توانید برای یک کوئری بیش از یک شرط تعریف کنید و در‌واقع کوئری نهایی and همه این شرایط می باشد.

query.notEqualTo("playerName", "Michael Yabuti");
query.greaterThan("playerAge", 18);

هم‌چنین می‌توانید با دستور زیر کاری کنید که به «تعدادی تصادفی» از اشیایی که در شرایط شما صدق می‌کنند، بازیابی شوند و نه همه‌ی اشیا.

query.sample(3);    // returns 3 random records

شما می‌توانید تعداد اشیایی که بازیابی می‌شوند را به یک عددی محدود کنید. به صورت پیش فرض، حداکثر ۱۰۰ شیء بازیابی می شود. شما می‌توانید یک عدد بین ۰ تا ۱۰۰۰ به عنوان limit تعیین کنید.

query.limit(10); // limit to at most 10 results

اگر می‌خواهید چند شیء اولی که قرار است بازیابی شوند skip شوند و در نظر گرفته نشوند، می‌توانید از دستور skip استفاده کنید. این دستور در بحث pagination بسیار سودمند می باشد.

query.skip(10); // skip the first 10 results

شما می‌توانید هم چنین ترتیب اشیایی که بازیابی می‌شوند را بر اساس یکی از ویژگی‌های آن کنترل کنید.

// Sorts the results in ascending order by the score field
query.ascending("score");

// Sorts the results in descending order by the score field
query.descending("score");

برای نوع داده‌های قابل مرتب سازی، شما می‌توانید از شرط های مقایسه‌ای نیز استفاده کنید.

// Restricts to wins < 50
query.lessThan("wins", 50);

// Restricts to wins <= 50
query.lessThanOrEqualTo("wins", 50);

// Restricts to wins > 50
query.greaterThan("wins", 50);

// Restricts to wins >= 50
query.greaterThanOrEqualTo("wins", 50);

اگر می‌خواهید مثلاً بازیکنانی را که نام آن‌ها در یک لیستی که از قبل وجود دارد، بازیابی کنید، می‌توانید از متود containedIn به شکل زیر استفاده کنید.

// Finds scores from any of Jonathan, Dario, or Shawn
query.containedIn("playerName", ["Jonathan Walsh", "Dario Wunsch", "Shawn Simon"]);

هم چنین بالعکس حالت قبل، اگر می‌خواهید بازیکنانی را بازیابی کنید که نام آن‌ها در یک لیست نباشد، می‌توانید از دستور notContainedIn استفاده کنید.

// Finds scores from anyone who is neither Jonathan, Dario, nor Shawn
query.notContainedIn("playerName", ["Jonathan Walsh", "Dario Wunsch", "Shawn Simon"]);

اگر می‌خواهید بازیکنانی را بازیابی کنید که یک فیلد score برای آن‌ها مقدار داشته باشد یا نباشد، می‌توانید از دستور های exists و doesNotExist استفاده کنید.

// Finds objects that have the score set
query.exists("score");

// Finds objects that don't have the score set
query.doesNotExist("score");

شما می‌توانید از متود matchesKeyInQuery برای یافتن اشیایی که یک مشخصه با کلیدی که در یک کوئری دیگر بازیابی می شود، تطابقت می کند، استفاده کنید. برای مثال، فرض کنید کلاسی شامل تیم های فوتبال دارید و هم چنین شما زادگاه هر بازیکن را در کلاس بازیکن ذخیره می کنید. شما می‌توانید لیست بازیکنانی را بیابید که تیم های زادگاهشان، بیش از نیمی از بازی‌ها را برنده شده اند. این کوئری به صورت زیر خواهد شد.

var Player = Backtory.Object.extend("Player");
var Team = Backtory.Object.extend("Team");
var teamQuery = new Backtory.Query(Team);
teamQuery.greaterThan("winPct", 0.5);
var userQuery = new Backtory.Query(Player);
userQuery.matchesKeyInQuery("hometown", "city", teamQuery);
userQuery.find({
    success: function(results) {
        // results has the list of users with a hometown team with a winning record
    },
    error: function(error) {
        // There was an error.
    }
});

بالعکس، این امر هم با متود doesNotMatchKeyInQuery قابل پیاده‌سازی می باشد.

var Player = Backtory.Object.extend("Player");
var losingUserQuery = new Backtory.Query(Player);
losingUserQuery.doesNotMatchKeyInQuery("hometown", "city", teamQuery);
losingUserQuery.find({
    success: function(results) {
        // results has the list of users with a hometown team with a losing record
    },
    error: function(error) {
        // There was an error.
    }
});

شما می‌توانید مشخصه های اشیایی که توسط find بازیابی می‌شوند را با استفاده از دستور select به تعدادی خاص، محدود کنید. برای مثال شما می‌توانید که هنگام بازیابی GameScore ها، کاری کنید که فقط مشخصه های score و playerName آن‌ها بازیابی شود.

var GameScore = Backtory.Object.extend("GameScore");
var query = new Backtory.Query(GameScore);
query.select("score", "playerName");
query.find({
    success: function(results) {
        // each of results will only have the selected fields available.
    },
    error: function(error) {
        // There was an error.
    }
});

شما می توانید بقیه فیلدها را در صورت لزوم بعداً با فراخوانی دستور fetch بر روی شیء مورد نظر بازیابی کنید.

بازیابی مقادیر آرایه ای

برای مشخصه های از نوع آرایه، می‌توانید فقط آن اشیایی را بازیابی کنید که مشخصه مربوط به آرایه شان دارای مقدار خاصی باشد.

// Find objects where the array in arrayKey contains 2.
query.equalTo("arrayKey", 2);

هم چنین می‌توانید آن‌هایی را بازیابی کنید که مشخصه آرایه شان همه مقادیر آرایه دیگر را داشته باشد.

// Find objects where the array in arrayKey contains all of the elements 2, 3, and 4.
query.containsAll("arrayKey", [2, 3, 4]);

بازیابی مقادیر رشته ای

شما می‌توانید با استفاده از دستور startsWith فقط بازیکنانی را بازیابی کنید که نام آن‌ها با رشته ای خاص شروع شود.

// Finds players that their name start with "Rob".
var query = new Backtory.Query(Player);
query.startsWith("name", "Rob");

مانند عملگر های MySQL، این شاخص گذاری شده است و برای دیتاهای بزرگ نیز به صورت بسیار بهینه ای کار می کند.

هم چنین با استفاده از دستور contains می توانید بازکنانی را بازیابی کنید که نام آن ها شامل رشته خاصی باشد.

// Finds players that their name contains "bob".
var query = new Backtory.Query(Player);
query.contains("name", "bob");

بازیابی رابطه ای

روش‌های متعددی برای بازیابی داده‌هایی که شامل رابطه می باشند، وجود دارد. اگر می‌خواهید اشیایی را بازیابی کنید که یک فیلد (از نوع پوینتر) با یک Backtory.Object دیگر تطابقت دارد، می‌توانید از همان دستور equalTo استفاده کنید.

// Assume Backtory.Object myPost was previously created.
var query = new Backtory.Query(Comment);
query.equalTo("post", myPost);
query.find({
    success: function(comments) {
        // comments now contains the comments for myPost
    },
    error: function(error) {
        // There was an error.
    }
});

اگر می‌خواهید اشیایی را بازیابی کنید که دارای یک فیلد پوینتر (Backtory.Object) می‌باشند و می‌خواهید آن فیلد با نتیجه یک کوئری دیگر تطابق داشته باشد، کافیست از متود mathesQuery استفاده کنید.

var Post = Backtory.Object.extend("Post");
var Comment = Backtory.Object.extend("Comment");
var innerQuery = new Backtory.Query(Post);
innerQuery.exists("image");
var query = new Backtory.Query(Comment);
query.matchesQuery("post", innerQuery);
query.find({
    success: function(comments) {
        // comments now contains the comments for posts with images.
    },
    error: function(error) {
        // There was an error.
    }
});

به طور مشابه در حالتی که نمی‌خواهید تطابق داشته باشد، کافیست از دستور doesNotMatchQuery استفاده کنید.

var Post = Backtory.Object.extend("Post");
var Comment = Backtory.Object.extend("Comment");
var innerQuery = new Backtory.Query(Post);
innerQuery.exists("image");
var query = new Backtory.Query(Comment);
query.doesNotMatchQuery("post", innerQuery);
query.find({
    success: function(comments) {
        // comments now contains the comments for posts without images.
    },
    error: function(error) {
        // There was an error.
    }
});

شما هم چنین می‌توانید با استفاده از فیلد _id یک شیء بازیابی رابطه‌ای به شکل زیر انجام دهید.

var post = new Post();
post.id = "1zEcyElZ80";
query.equalTo("post", post);

در شرایطی خاص ممکن است بخواهید که پوینتر هایی که درون یک شیء هستند نیز هنگامی که آن شیء بازیابی می شود، به صورت کامل بازیابی شوند. برای این کار کافیست دستور include را برای کلید های مربوطه صدا بزنید.

var query = new Backtory.Query(Comment);

// Retrieve the most recent ones
query.descending("createdAt");

// Only retrieve the last ten
query.limit(10);

// Include the post data with each comment
query.include("post");

query.find({
    success: function(comments) {
        // Comments now contains the last ten comments, and the "post" field
        // has been populated. For example:
        for (var i = 0; i < comments.length; i++) {
            // This does not require a network access.
            var post = comments[i].get("post");
        }
    },
    error: function(error) {
        // There was an error.
    }
});

شمردن اشیا

اگر صرفاً می‌خواهید بفهمید چند شیء در یک کوئری خاص صدق می کنند، می‌توانید از متود count استفاده کنید.

var GameScore = Backtory.Object.extend("GameScore");
var query = new Backtory.Query(GameScore);
query.equalTo("playerName", "Sean Plott");
query.count({
    success: function(count) {
        // The count request succeeded. Show the count
        context.log("Sean has played " + count + " games");
    },
    error: function(error) {
        // The request failed
    }
});

کوئری های مرکب

اگر می‌خواهید دو یا چند کوئری را با هم ترکیب کنید و اشیایی را بازیابی کنید که در حداقل یکی از کوئری ها صدق کنند می‌توانید از دستور Backtory.Query.or به شکل زیر استفاده کنید.

var lotsOfWins = new Backtory.Query("Player");
lotsOfWins.greaterThan("wins", 150);

var fewWins = new Backtory.Query("Player");
fewWins.lessThan("wins", 5);

var mainQuery = Backtory.Query.or(lotsOfWins, fewWins);
mainQuery.limit(3);
mainQuery.find({
    success: function(results) {
        // results contains a list of players that either have won a lot of games or won only a few games.
    },
    error: function(error) {
        // There was an error.
    }
});

گام بعدی