03.查询Queries

查询

我们已经看到了Parse.Query如何使用get从Parse中检索一个Parse.Object。Parse.Query还有许多其他方法来检索数据——您可以一次检索多个对象、在待检索对象上添加条件等等。

1.基本查询

在许多情况下,get还不够强大到足以明确要检索的对象。Parse.Query提供了不同的方式来检索一组对象列表,而不仅仅是单个对象。

一般模式是创建一个Parse.Query,放置条件,然后使用find检索一组匹配的Parse.Object。例如,要检索具有特定playerName的分数,可使用equalTo方法来约束一个键的值。

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

2.查询约束

有几种方法来为Parse.Query找到的对象提供约束条件。您可以使用notEqualTo过滤出具有特定键值对的对象:

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

您可以给出多个约束,只有匹配所有约束的对象才会出现在结果中。换句话说,它就像一个AND约束条件。

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

您可以通过设置limit限制结果数量。默认情况下,返回结果被限制为100。在旧的Parse托管后端中,最大约束为1,000,但是Parse Server删除了该约束:

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

如果你只想要一个结果,更方便的替代方法是使用first而不是使用find。

var GameScore = Parse.Object.extend("GameScore");
var query = new Parse.Query(GameScore);
query.equalTo("playerEmail", "dstemkoski@example.com");
query.first({
  success: function(object) {
    // Successfully retrieved the object.
  },
  error: function(error) {
    alert("Error: " + error.code + " " + error.message);
  }
});

您可以通过设置skip跳过第一个结果。在旧的Parse托管后端中,最大跳过值为10,000,但Parse Server删除了该约束。这对分页有用:

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"]);

如果要检索具有特定键集的对象,可以使用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方法来获取这样的对象:查询中的某个键与另一个查询产生的一组对象中某个键的值相匹配。例如,如果您有一个包含运动队的类(译者注:包含“city”字段),且用户类中存储有用户的家乡(译者注:包含“hometown”字段),则可以发起一个查询来查找其家乡运动队具有获胜记录的用户列表。查询将如下所示:

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

相反的,要获取其中某个键与另一个查询产生的一组对象中某个键的值不匹配的对象,请使用doesNotMatchKeyInQuery。例如,要找到家乡团队有失败记录的用户:

var losingUserQuery = new Parse.Query(Parse.User);
losingUserQuery.doesNotMatchKeyInQuery("hometown", "city", teamQuery);
losingUserQuery.find({
  success: function(results) {
    // results has the list of users with a hometown team with a losing record
  }
});

您可以调用包含一组键的select来限定返回的字段。要检索仅包含score和playerName字段的文档(当然还包括如objectId、createdAt和updatedAt的特别内置字段):

var GameScore = Parse.Object.extend("GameScore");
var query = new Parse.Query(GameScore);
query.select("score", "playerName");
query.find().then(function(results) {
  // each of results will only have the selected fields available.
});

剩余字段可以稍后通过在返回的对象上调用fetch来获取:

query.first().then(function(result) {
  // only the selected fields of the object will now be available here.
  return result.fetch();
}).then(function(result) {
  // all fields of the object will now be available here.
});

3.查询数组值

对于具有数组类型的键,可以通过以下方式找到键的数组值为2的对象:

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

您还可以查找键的数组值包含2,3和4的对象:

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

4.查询字符串值

如果您正在尝试实现通用的搜索功能,我们建议您查看此博文:在NoSQL后端实现可扩展搜索

可使用startsWith来检索以特定字符串开头的字符串值。与MySQL LIKE运算符类似,它是有索引的,因此对于大型数据集它也很高效:

// Finds barbecue sauces that start with "Big Daddy's".
var query = new Parse.Query(BarbecueSauce);
query.startsWith("name", "Big Daddy's");

上述示例将匹配BarbecueSauce中“name”键中的值以“Big Daddy's”开头的任何对象。例如,“Big Daddy’s”和“Big Daddy’s BBQ”都会匹配,但是“big daddy’s”和“BBQ Sauce: Big Daddy’s”不会。

具有正则表达式约束的查询代价非常昂贵,特别是对于超过100,000条记录的类。Parse限制了在给定时间内应用程序运行这样操作的次数。

5.关系型查询

有几种方式来发起关系数据查询。如果要检索与特定Parse.Object字段匹配的对象,可以像其他数据类型一样使用equalTo。例如,如果每个Comment的post字段中都有一个Post对象,则可这样获取针对特定Post的comments:

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

如果要检索对象的某个字段包含从别的查询中匹配的对象,可以使用matchesQuery。为了找到包含图像的帖子的评论,你可以这样做:

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

如果要检索对象的某个字段包含从别的查询中不匹配的对象,可以使用doesNotMatchQuery。为了找到没有图像的帖子的评论,你可以这样:

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

您还可以通过objectId进行关系查询:

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

在某些情况下,您希望在一个查询中返回多种类型的相关对象,则可以使用include方法。例如,假设您正在检索最近十条评论,并同步检索出与之相关的帖子:

var query = new Parse.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");
    }
  }
});

您还可以使用点标记进行多级包含。如果你想包括某个评论有关的帖子和帖子的作者,你可以做:

query.include(["post.author"]);

您可以通过多次调用include以在查询中包含多个字段。此功能也适用于Parse.Query助手,如first和get。

6.计数对象

注意:在旧的Parse托管后端中,计数查询的频度限制为每分钟最多请求160次。而且当类中超过1000个对象时还会返回不准确的结果。不过,Parse Server已经删除了这两个限制,在对象超过1000时计数也工作良好。

如果您只需要计算与查询匹配的对象数量,而不需要检索出所有匹配的对象,则可以使用count而不是find。例如,计算特定玩家玩过的游戏数量:

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

7.复合查询

如果要查找的对象只匹配几个查询条件中的一个,可以使用Parse.Query.or方法,该方法传入的查询条件之间是OR的关系。例如,如果您想要查找有很多胜利或少数胜利的玩家, 你可以这样:

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

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

var mainQuery = Parse.Query.or(lotsOfWins, fewWins);
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.
  }
});

您可以为新创建的Parse.Query添加其他约束充当“and”运算符。

请注意,在复合查询的子查询中,我们不支持GeoPoint或非过滤型约束(例如near、withinGeoBox、limit、skip、ascending/descending、include)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • Django 1.8.2 文档Home | Table of contents | Index | Modules...
    轩辕小爱阅读 2,343评论 0 2
  • REST API 可以让你用任何支持发送 HTTP 请求的设备来与 Parse 进行交互,你可以使用 REST A...
    Caroline嗯哼阅读 1,987评论 0 0
  • 接下来的100天我要做以下6件事: 001 淘宝店铺的宝贝上架数量至少达到100个 标准:总数量达到100个,还要...
    一匹笑笑马阅读 206评论 0 0
  • 爱情总会出现这样那样的问题。刚和林锅出现了分歧。我们异地恋,但我们好久没有吵架了,我已经记不清上一次吵架是什么时候...
    牛掰闪闪阅读 617评论 0 0