try{// Build the SortOptions with 2 sort keysSortOptionssortOptions=SortOptions.newBuilder().addSortExpression(SortExpression.newBuilder().setExpression("price").setDirection(SortExpression.SortDirection.DESCENDING).setDefaultValueNumeric(0)).addSortExpression(SortExpression.newBuilder().setExpression("brand").setDirection(SortExpression.SortDirection.DESCENDING).setDefaultValue("")).setLimit(1000).build();// Build the QueryOptionsQueryOptionsoptions=QueryOptions.newBuilder().setLimit(25).setFieldsToReturn("model","price","description").setSortOptions(sortOptions).build();// A query stringStringqueryString="product: coffee roaster AND price < 500";// Build the Query and run the searchQueryquery=Query.newBuilder().setOptions(options).build(queryString);IndexSpecindexSpec=IndexSpec.newBuilder().setName(indexName).build();Indexindex=SearchServiceFactory.getSearchService().getIndex(indexSpec);Results<ScoredDocument>result=index.search(query);returnresult;}catch(SearchExceptione){// handle exception...}
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["很难理解","hardToUnderstand","thumb-down"],["信息或示例代码不正确","incorrectInformationOrSampleCode","thumb-down"],["没有我需要的信息/示例","missingTheInformationSamplesINeed","thumb-down"],["翻译问题","translationIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-08-21。"],[[["\u003cp\u003eThe \u003ccode\u003eQuery\u003c/code\u003e class allows customization of search results, including the number of documents returned, the content of those documents (IDs only, subsets of fields, custom fields), and the sorting order.\u003c/p\u003e\n"],["\u003cp\u003e\u003ccode\u003eQueryOptions\u003c/code\u003e control the number and order of results, enabling pagination through \u003ccode\u003eOffset\u003c/code\u003e or \u003ccode\u003eCursor\u003c/code\u003e, with \u003ccode\u003eLimit\u003c/code\u003e determining the maximum number of documents returned (up to 1000) and \u003ccode\u003eNumberFoundAccuracy\u003c/code\u003e controlling the precision of the result count.\u003c/p\u003e\n"],["\u003cp\u003e\u003ccode\u003eSortOptions\u003c/code\u003e manage the ordering and scoring of search results, supporting sorting on multiple keys via \u003ccode\u003eSortExpressions\u003c/code\u003e, custom scoring with \u003ccode\u003eMatchScorer\u003c/code\u003e, and defining a \u003ccode\u003eLimit\u003c/code\u003e for the number of documents to be sorted (defaulting to 1,000, max 10,000).\u003c/p\u003e\n"],["\u003cp\u003eExpressions, used in both \u003ccode\u003eQueryOptions\u003c/code\u003e and \u003ccode\u003eSortOptions\u003c/code\u003e, can be written as strings and include arithmetical operators, built-in numeric functions (\u003ccode\u003emax\u003c/code\u003e, \u003ccode\u003emin\u003c/code\u003e, \u003ccode\u003elog\u003c/code\u003e, \u003ccode\u003eabs\u003c/code\u003e, \u003ccode\u003epow\u003c/code\u003e, \u003ccode\u003ecount\u003c/code\u003e), geopoint functions (\u003ccode\u003egeopoint\u003c/code\u003e, \u003ccode\u003edistance\u003c/code\u003e), and special terms like \u003ccode\u003e_rank\u003c/code\u003e and \u003ccode\u003e_score\u003c/code\u003e.\u003c/p\u003e\n"],["\u003cp\u003eSnippets, text fragments highlighting query matches within a field, can be generated using the \u003ccode\u003esnippet\u003c/code\u003e function, which takes a query string, field name, and an optional character limit, and returns an HTML string with the matching text in boldface.\u003c/p\u003e\n"]]],[],null,["# Query and Sorting Options\n\n| This API is supported for first-generation runtimes and can be used when [upgrading to corresponding second-generation runtimes](/appengine/docs/standard/\n| java-gen2\n|\n| /services/access). If you are updating to the App Engine Java 11/17 runtime, refer to the [migration guide](/appengine/migration-center/standard/migrate-to-second-gen/java-differences) to learn about your migration options for legacy bundled services.\n\nWhen you call the\n`search()` method using a query string alone, the results are\nreturned according to the default query options:\n\n- Documents are returned sorted in order of descending rank\n- Documents are returned in groups of 20 at a time\n- Retrieved documents contain all of their original fields\n\nYou can use an instance of the\n\n[Query](/appengine/docs/legacy/standard/java/javadoc/com/google/appengine/api/search/Query) class\n\n\nas the argument to `search()`\nto change these options.\n\nThe Query class allows you to specify how many documents to\nreturn at a time. It also lets you customize the contents of the retrieved\ndocuments. You can ask for document identifiers only, or request that documents\ncontain only a subset of their fields. You can also create custom fields in the\nretrieved documents:\n[snippets](#snippets) (fragments of text fields showing the text surrounding a\nmatched string), and\n[field expressions](#FieldExpressions) (fields with values\nderived from other fields in the document).\n\nApart from the query options, the\nQuery class\ncan also include an instance of the `SortOptions`\nclass. Using sort options you can\nchange the sort order, and sort the results on multiple keys.\n\nSearching with the Query class\n------------------------------\n\nWhen you search with an instance of the Query class, you need to construct an\ninstance of the class in several steps. This is the general order:\n\n1. Create a query string.\n2. Create `SortOptions` if needed.\n3. Create `QueryOptions`.\n4. Create a Query object that includes the query string and the (optional) `QueryOptions`.\n5. Call the search method on the Query object.\n\nThe various query and sort options are specified by calling setter methods on\ninstances of the `QueryOptions.Builder` and `SortOptions.Builder` classes, as in\nthis example: \n\n try {\n // Build the SortOptions with 2 sort keys\n SortOptions sortOptions =\n SortOptions.newBuilder()\n .addSortExpression(\n SortExpression.newBuilder()\n .setExpression(\"price\")\n .setDirection(SortExpression.SortDirection.DESCENDING)\n .setDefaultValueNumeric(0))\n .addSortExpression(\n SortExpression.newBuilder()\n .setExpression(\"brand\")\n .setDirection(SortExpression.SortDirection.DESCENDING)\n .setDefaultValue(\"\"))\n .setLimit(1000)\n .build();\n\n // Build the QueryOptions\n QueryOptions options =\n QueryOptions.newBuilder()\n .setLimit(25)\n .setFieldsToReturn(\"model\", \"price\", \"description\")\n .setSortOptions(sortOptions)\n .build();\n\n // A query string\n String queryString = \"product: coffee roaster AND price \u003c 500\";\n\n // Build the Query and run the search\n Query query = Query.newBuilder().setOptions(options).build(queryString);\n IndexSpec indexSpec = IndexSpec.newBuilder().setName(indexName).build();\n Index index = SearchServiceFactory.getSearchService().getIndex(indexSpec);\n Results\u003cScoredDocument\u003e result = index.search(query);\n return result;\n } catch (SearchException e) {\n // handle exception...\n }\n\nQueryOptions\n------------\n\nYou must use the [`QueryOptions.Builder`](/appengine/docs/legacy/standard/java/javadoc/com/google/appengine/api/search/QueryOptions.Builder) to set query options. You do not have access to these properties directly.\n\nThese properties control how many results are returned and in what order. The\noffset and cursor options, which are mutually exclusive, support pagination.\nThey specify which selected documents to return in the results.\n\nThese properties control what document fields appear in the results.\n\nSortOptions\n-----------\n\nThe properties of `SortOptions` control the ordering and scoring of the search\nresults. You must use the\n[`SortOptions.Builder`](/appengine/docs/legacy/standard/java/javadoc/com/google/appengine/api/search/SortOptions.Builder)\nto set the sort options. You do not have access to these properties directly.\n\nThe properties of `SortOptions` control the ordering and scoring of the search\nresults.\n\n### Sorting on multiple keys\n\nYou can order the search results on multiple sort keys. Each key can be a simple\nfield name, or a value that is computed from several fields.\nNote that the term 'expression' is used with multiple\nmeanings when speaking about sort options: The `SortOption` itself has an\n*expressions attribute* . This attribute is a list of `SortExpression` objects\nwhich correspond to sort keys. Finally, each `SortExpression` object contains an\n*expression attribute* which specifies how to calculate the value of the sort\nkey. This expression is constructed according to the rules in the\nnext section.\n\nA `SortExpression` also defines the direction of the sort and a default key\nvalue to use if the expression cannot be calculated for a document. Here is the\ncomplete list of properties:\n\n### Sorting on multi-valued fields\n\nWhen you sort on a multi-valued field of a particular type, only the first value assigned to the field is used. For example, consider two documents, DocA and DocB that both have a text field named \"color\". Two values are assigned to the DocA \"color\" field in the order (red, blue), and two values to DocB in the order (green, red). When you perform a sort specifying the text field \"color\", DocA is sorted on the value \"red\" and DocB on the value \"green\". The other field values are not used in the sort.\n\n### To sort or not to sort\n\nIf you do not specify any sort options, your search results are automatically\nreturned sorted by descending rank. There is no limit to the number of documents\nthat are returned in this case. If you specify any sorting options, the sort is\nperformed after all the matching documents have been selected. There is an\nexplicit property,\n\\`SortOptions.limit\\`\n, that controls the size\nof the sort. You can never sort more than 10,000 docs, the default is 1,000. If\nthere are more matching documents than the number specified by\n\\`SortOptions.limit\\`\n, search only retrieves, sorts,\nand returns that limited number. It selects the documents to sort from the list\nof all matching documents, which is in descending rank order. It is possible\nthat a query might select more matching documents than you can sort. If you are\nusing sort options and it is important to retrieve every matching document, you\nshould try to ensure that your query will return no more documents than you can\nsort.\n\nWriting expressions\n-------------------\n\nExpressions are used to define field expressions (which are set in the\n\\`QueryOptions\\`\n) and sort expressions, which are\nset in the `SortOptions`. They are written as strings: \n\n \"price * quantity\"\n \"(men + women)/2\"\n \"min(daily_use, 10) * rate\"\n \"snippet('rose', flower, 120)\"\n\nExpressions involving Number fields can use the arithmetical operators\n(+, -, \\*, /) and the built-in numeric functions listed below. Expressions\ninvolving geopoint fields can use the geopoint and distance functions.\nExpressions for Text and HTML fields can use the snippet function.\n\nExpressions can also include these special terms:\n\n### Numeric functions\n\nThe expressions to define numeric values for `FieldExpressions` and `SortExpressions` can use these built-in functions. The arguments must be numbers, field names, or expressions using numbers and field names.\n\n### Geopoint functions\n\nThese functions can be used for expressions involving geopoint fields.\n\n### Snippets\n\nA snippet is a fragment of a text field that matches a query string and includes\nthe surrounding text. Snippets are created by calling the `snippet` function:\n\n\n`snippet(query, body, [max_chars])`\n\n`query`\n: A quoted query string specifying the text to find in the field.\n\n`body`\n: The name of a text, HTML, or atom field.\n\n`max_chars`\n: The maximum number of characters to return in the snippet. This\n argument is optional; it defaults to 160 characters.\n\nThe function returns an HTML string. The string contains a snippet of the body\nfield's value, with the text that matched the query in boldface."]]