This is the legacy 4D documentation web site. Documentations are progressively being moved to developer.4d.com |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
4D v19.8
dataClass.query( )
|
dataClass.query ( queryString | formula {; value}{; value2 ; ... ; valueN}{; querySettings}) -> Result | ||||||||
Parameter | Type | Description | ||||||
queryString | formula | Text, Object |
![]() |
Search criteria as string or formula object | |||||
value | Mixed |
![]() |
Value(s) to use for indexed placeholder(s) | |||||
querySettings | Object |
![]() |
Query options: parameters, attributes, args, allowFormulas, context, queryPath, queryPlan | |||||
Result | EntitySelection |
![]() |
New entity selection made up of entities from dataClass meeting the search criteria specified in queryString or formula | |||||
The dataClass.query( ) method searches for entities that meet the search criteria specified in queryString or formula and (optionally) value(s), for all the entities in the dataclass, and returns a new object of type EntitySelection containing all the entities that are found. Lazy loading is applied.
If no matching entities are found, an empty EntitySelection is returned.
The queryString parameter uses the following syntax:
attributePath|formula comparator value {logicalOperator attributePath|formula comparator value} {order by attributePath {desc | asc}}
where:
Note: You cannot use directly attributes whose name contains special characters such as ".", "[ ]", or "=", ">", "#"..., because they will be incorrectly evaluated in the query string. If you need to query on such attributes, you must consider using placeholders, which allow an extended range of characters in attribute paths (see Using placeholders below).
"eval(length(This.lastname) >=30)"
(*) if the formula is not the only search criteria, the query engine optimizer could prior process other criteria (e.g. indexed attributes) and thus, the formula could be evaluated for only a subset of entities.
Formulas in queries can receive parameters through $1. This point is detailed in the formula parameter paragraph below.
Notes:
- You can also pass directy a formula parameter object instead of the queryString parameter (recommended when formulas are more complex). See formula parameter paragraph below.
- For security reasons, formula calls within query() member methods can be disallowed. See querySettings parameter description.
Comparison | Symbol(s) | Comment |
Equal to | =, == | Gets matching data, supports the wildcard (@), neither case-sensitive nor diacritic. |
===, IS | Gets matching data, considers the @ as a standard character, neither case-sensitive nor diacritic | |
Not equal to | #, != | Supports the wildcard (@) |
!==, IS NOT | Considers the @ as a standard character | |
Less than | < | |
Greater than | > | |
Less than or equal to | <= | |
Greater than or equal to | >= | |
Included in | IN | Gets data equal to at least one of the values in a collection or in a set of values, supports the wildcard (@) |
Not condition applied on a statement | NOT | Parenthesis are mandatory when NOT is used before a statement containing several operators |
Contains keyword | % | Keywords can be used in attributes of string or picture type |
Conjunction | Symbol(s) |
AND | &, &&, and |
OR | |, ||, or |
Using quotes
When you use quotes within queries, you must use single quotes ' ' inside the query and double quotes " " to enclose the whole query, otherwise an error is returned. For example:
"employee.name = 'smith' AND employee.firstname = 'john'"
Note: Single quotes (') are not supported in searched values since they would break the query string. For example "comp.name = 'John's pizza' " will generate an error. If you need to search on values with single quotes, you may consider using placeholders (see below).
Using parenthesis
You can use parentheses in the query to give priority to the calculation. For example, you can organize a query as follows:
"(employee.age >= 30 OR employee.age <= 65) AND (employee.salary <= 10000 OR employee.status = 'Manager')"
As an alternative to formula insertion within the queryString parameter (see above), you can pass directly a formula object as a boolean search criteria. Using a formula object for queries is recommended since you benefit from tokenization, and code is easier to search/read.
The formula must have been created using the Formula or Formula from string command. In this case:
Note: For security reasons, formula calls within query() member methods can be disallowed. See querySettings parameter description.
Passing parameters to formulas
Any formula called by the query() member method can receive parameters:
This small code shows the principles of how parameter are passed to methods:
$settings:=New object("args";New object("exclude";"-")) //args object to pass parameters
$es:=ds.Students.query("eval(checkName($1.exclude))";$settings) //args is received in $1
Additional examples are provided in example 3.
4D Server: In client/server, formulas are executed on the server. In this context, only the querySettings.args object is sent to the formulas.
4D allows you to use placeholders for attributePath, formula and value arguments within the queryString parameter. A placeholder is a parameter that you insert in query strings and that is replaced by another value when the query string is evaluated. The value of placeholders is evaluated once at the beginning of the query; it is not evaluated for each element.
Two types of placeholders can be used: indexed placeholders and named placeholders:
- | Indexed placeholders | Named placeholders |
Definition | Parameters are inserted as :paramIndex (for example :1, :2...) in queryString and their corresponding values are provided by the sequence of value parameter(s). You can use up to 128 value parameters | Parameters are inserted as :paramName (for example :myparam) and their values are provided in the attributes and/or parameters objects in the querySettings parameter |
Example | $r:=class.query(":1=:2";"city";"Chicago") | $o.attributes:=New object("att";"city") |
You can mix all argument kinds in queryString. A queryString can contain, for attributePath, formula and value parameters:
Using placeholders in queries is recommended for the following reasons:
$vquery:="status = 'public' & name = "+myname //user enters their name
$result:=$col.query($vquery)
$result:=$col.query("status='public' & name=:1";myname)
$result:=$col.query("address.city = :1 & name =:2";$city;$myVar+"@")
$result2:=$col.query("company.name = :1";"John's Pizzas")
Looking for null values
When you look for null values, you cannot use the placeholder syntax because the query engine considers null as an unexpected comparison value. For example, if you execute the following query:
$vSingles:=ds.Person.query("spouse = :1";Null) // will NOT work
$vSingles:=ds.Person.query("spouse = null") //correct syntax
When searching in collections within object attributes using multiple query arguments joined by the AND operator, you may want to make sure that only entities containing elements that match all arguments are returned, and not entities where arguments can be found in different elements. To do this, you need to link query arguments to collection elements, so that only single elements containing linked arguments are found.
For example, with the following two entities:
Entity 1:
ds.People.name: "martin"
ds.People.places:
{ "locations" : [ {
"kind":"home",
"city":"paris"
} ] }
Entity 2:
ds.People.name: "smith"
ds.People.places:
{ "locations" : [ {
"kind":"home",
"city":"lyon"
} , {
"kind":"office",
"city":"paris"
} ] }
You want to find people with a "home" location kind in the city "paris". If you write:
ds.People.query("places.locations[].kind= :1 and places.locations[].city= :2";"home";"paris")
... the query will return "martin" and "smith" because "smith" has a "locations" element whose "kind" is "home" and a "locations" element whose "city" is "paris", even though they are different elements.
If you want to only get entities where matching arguments are in the same collection element, you need to link arguments. To link query arguments:
With the above entities, if you write:
ds.People.query("places.locations[a].kind= :1 and places.locations[a].city= :2";"home";"paris")
... the query will only return "martin" because it has a "locations" element whose "kind" is "home" and whose "city" is "paris". The query will not return "smith" because the values "home" and "paris" are not in the same collection element.
In the querySettings parameter, you can pass an object containing additional options. The following properties are supported:
Property | Type | Description | ||||||
parameters | Object | Named placeholders for values used in the queryString or formula. Values are expressed as property / value pairs, where property is the placeholder name inserted for a value in the queryString or formula (":placeholder") and value is the value to compare. You can mix indexed placeholders (values directly passed in value parameters) and named placeholder values in the same query. | ||||||
attributes | Object | Named placeholders for attribute paths used in the queryString or formula. Attributes are expressed as property / value pairs, where property is the placeholder name inserted for an attribute path in the queryString or formula (":placeholder"), and value can be a string or a collection of strings. Each value is a path that can designate either a scalar or a related attribute of the dataclass or a property in an object field of the dataclass
| ||||||
args | Object | Parameter(s) to pass to formulas, if any. The args object will be received in $1 within formulas and thus its values will be available through $1.property (see example 3). | ||||||
allowFormulas | Boolean | True to allow the formula calls in the query (default). Pass false to disallow formula execution. If set to false and query() is given a formula, an error is sent (1278 - Formula not allowed in this member method). | ||||||
context | Text | Label for the automatic optimization context applied to the entity selection. This context will be used by the code that handles the entity selection so that it can benefit from the optimization. This feature is designed for client/server processing; for more information, please refer to the Client/server optimization section. | ||||||
queryPlan | Boolean | In the resulting entity selection, returns or does not return the detailed description of the query just before it is executed, i.e. the planned query. The returned property is an object that includes each planned query and subquery (in the case of a complex query). This option is useful during the development phase of an application. It is usually used in conjunction with queryPath. Default if omitted: false. Note: This property is supported only by the entitySelection.query( ) and dataClass.query( ) methods. | ||||||
queryPath | Boolean | In the resulting entity selection, returns or does not return the detailed description of the query as it is actually performed. The returned property is an object that contains the actual path used for the query (usually identical to that of the queryPlan, but may differ if the engine manages to optimize the query), as well as the processing time and the number of records found. This option is useful during the development phase of an application. Default if omitted: false. Note: This property is supported only by the entitySelection.query( ) and dataClass.query( ) methods. |
About queryPlan and queryPath
The information recorded in queryPlan/queryPath includes the query type (indexed and sequential) and each necessary subquery along with conjunction operators. Query paths also contain the number of entities found and the time required to execute each search criterion. You may find it useful to analyze this information while developing your application(s). Generally, the description of the query plan and its path are identical but they can differ because 4D can implement dynamic optimizations when a query is executed in order to improve performance. For example, the 4D engine can dynamically convert an indexed query into a sequential one if it estimates that it is faster. This particular case can occur when the number of entities being searched for is low.
For example, if you execute the following query:
$sel:=ds.Employee.query("salary < :1 and employer.name = :2 or employer.revenues > :3";50000;"Lima West Kilo";10000000;New object("queryPath";True;"queryPlan";True))
queryPlan:
{Or:[{And:[{item:[index : Employee.salary ] < 50000},{item:Join on Table : Company : Employee.employerID = Company.ID,subquery:[{item:[index : Company.name ] = Lima West Kilo}]}]},{item:Join on Table : Company : Employee.employerID = Company.ID,subquery:[{item:[index : Company.revenues ] > 10000000}]}]}
queryPath:
{steps:[{description:OR,time:63,recordsfounds:1388132,steps:[{description:AND,time:32,recordsfounds:131,steps:[{description:[index : Employee.salary ] < 50000,time:16,recordsfounds:728260},{description:Join on Table : Company : Employee.employerID = Company.ID,time:0,recordsfounds:131,steps:[{steps:[{description:[index : Company.name ] = Lima West Kilo,time:0,recordsfounds:1}]}]}]},{description:Join on Table : Company : Employee.employerID = Company.ID,time:31,recordsfounds:1388132,steps:[{steps:[{description:[index : Company.revenues ] > 10000000,time:0,recordsfounds:933}]}]}]}]}
This section provides various examples of queries.
Query on a string:
$entitySelection:=ds.Customer.query("firstName = 'S@'")
Query with a NOT statement:
$entitySelection:=ds.Employee.query("not(firstName=Kim)")
Queries with dates:
$entitySelection:=ds.Employee.query("birthDate > :1";"1970-01-01")
$entitySelection:=ds.Employee.query("birthDate <= :1";Current date-10950)
Query with indexed placeholders for values:
$entitySelection:=ds.Customer.query("(firstName = :1 or firstName = :2) and (lastName = :3 or lastName = :4)";"D@";"R@";"S@";"K@")
Query with indexed placeholders for values on a related dataClass:
$entitySelection:=ds.Employee.query("lastName = :1 and manager.lastName = :2";"M@";"S@")
Query with indexed placeholder including a descending order by statement:
$entitySelection:=ds.Student.query("nationality = :1 order by campus.name desc, lastname";"French")
Query with named placeholders for values:
C_OBJECT($querySettings;$managedCustomers)
$querySettings:=New object
$querySettings.parameters:=New object("userId";1234;"extraInfo";New object("name";"Smith"))
$managedCustomers:=ds.Customer.query("salesperson.userId = :userId and name = :extraInfo.name";$querySettings)
Query that uses both named and indexed placeholders for values:
C_OBJECT($querySettings;$managedCustomers)
$querySettings:=New object
$querySettings.parameters:=New object("userId";1234)
$managedCustomers:=ds.Customer.query("salesperson.userId = :userId and name=:1";"Smith";$querySettings)
Query with queryPlan and queryPath objects:
$entitySelection:=ds.Employee.query("(firstName = :1 or firstName = :2) and (lastName = :3 or lastName = :4)";"D@";"R@";"S@";"K@";New object("queryPlan";True;"queryPath";True))
//you can then get these properties in the resulting entity selection
C_OBJECT($queryPlan;$queryPath)
$queryPlan:=$entitySelection.queryPlan
$queryPath:=$entitySelection.queryPath
Query with an attribute path of Collection type:
$entitySelection:=ds.Employee.query("extraInfo.hobbies[].name = :1";"horsebackriding")
Query with an attribute path of Collection type and linked attributes:
$entitySelection:=ds.Employee.query("extraInfo.hobbies[a].name = :1 and extraInfo.hobbies[a].level=:2";"horsebackriding";2)
Query with an attribute path of Collection type and multiple linked attributes:
$entitySelection:=ds.Employee.query("extraInfo.hobbies[a].name = :1 and extraInfo.hobbies[a].level = :2 and extraInfo.hobbies[b].name = :3 and extraInfo.hobbies[b].level = :4";"horsebackriding";2;"Tennis";5)
Query with an attribute path of Object type:
$entitySelection:=ds.Employee.query("extra.eyeColor = :1";"blue")
Query with an IN statement:
$entitySelection:=ds.Employee.query("firstName in :1";New collection("Kim";"Dixie"))
Query with a NOT (IN) statement:
$entitySelection:=ds.Employee.query("not (firstName in :1)";New collection("John";"Jane"))
Query with indexed placeholders for attributes:
C_OBJECT($es)
$es:=ds.Employee.query(":1 = 1234 and :2 = 'Smith'";"salesperson.userId";"name")
//salesperson is a related entity
Query with indexed placeholders for attributes and named placeholders for values:
C_OBJECT($es;$querySettings)
$querySettings:=New object
$querySettings.parameters:=New object("customerName";"Smith")
$es:=ds.Customer.query(":1 = 1234 and :2 = :customerName";"salesperson.userId";"name";$querySettings)
//salesperson is a related entity
Query with indexed placeholders for attributes and values:
C_OBJECT($es)
$es:=ds.Clients.query(":1 = 1234 and :2 = :3";"salesperson.userId";"name";"Smith")
//salesperson is a related entity
This section illustrates queries with named placeholders for attributes.
Given an Employee dataclass with 2 entities:
Query with named placeholders for attributes:
C_OBJECT($querySettings;$es)
$querySettings:=New object
$querySettings.attributes:=New object("attName";"name";"attWord";New collection("softwares";"Word 10.2"))
$es:=ds.Employee.query(":attName = 'Marie' and :attWord = 'Installed'";$querySettings)
//$es.length=1 (Employee Marie)
Query with named placeholders for attributes and values:
C_OBJECT($es;$queySettings)
C_TEXT($name)
$querySettings:=New object
//Named placeholders for values
//The user is asked for a name
$name:=Request("Please enter the name to search:")
If(OK=1)
$querySettings.parameters:=New object("givenName";$name)
//Named placeholders for attribute paths
$querySettings.attributes:=New object("attName";"name")
$es:=ds.Employee.query(":attName= :givenName";$querySettings)
End if
These examples illustrate the various ways to use formulas with or without parameters in your queries.
The formula is given as text with eval() in the queryString parameter:
C_OBJECT($es)
$es:=ds.Students.query("eval(length(This.lastname) >=30) and nationality='French'")
The formula is given as a Formula object through a placeholder:
C_OBJECT($es;$formula)
$formula:=Formula(Length(This.lastname)>=30)
$es:=ds.Students.query(":1 and nationality='French'";$formula)
Only a Formula object is given as criteria:
C_OBJECT($es;$formula)
$formula:=Formula(Length(This.lastname)>=30)
$es:=ds.Students.query($formula)
Several formulas can be applied:
C_OBJECT($formula1;$1;$formula2;$0)
$formula1:=$1
$formula2:=Formula(Length(This.firstname)>=30)
$0:=ds.Students.query(":1 and :2 and nationality='French'";$formula1;$formula2)
A text formula in queryString receives a parameter:
C_OBJECT($es;$settings)
$settings:=New object()
$settings.args:=New object("filter";"-")
$es:=ds.Students.query("eval(checkName($1.filter)) and nationality=:1";"French";$settings)
//checkName method:
C_TEXT($1;$exclude)
$exclude:=$1
$0:=(Position($exclude;This.lastname)=0)
Using the same checkName method, a Formula object as placeholder receives a parameter:
C_OBJECT($es;$settings;$formula)
$formula:=Formula(checkName($1.filter))
$settings:=New object()
$settings.args:=New object("filter";"-")
$es:=ds.Students.query(":1 and nationality=:2";$formula;"French";$settings)
$settings.args.filter:="*" // change the parameters without updating the $formula object
$es:=ds.Students.query(":1 and nationality=:2";$formula;"French";$settings)
We want to disallow formulas, for example when the user enters their query:
C_OBJECT($es;$settings)
C_TEXT($queryString)
$queryString:=Request("Enter your query:")
if(OK=1)
$settings:=New object("allowFormulas";False)
$es:=ds.Students.query($queryString;$settings) //An error is raised if $queryString contains a formula
End if
4D Blog - Add values to your generic orda queries
4D Blog - Placeholders for attribute paths in ORDA queries
collection.query( )
dataClass.all( )
dataClass.newSelection( )
DESCRIBE QUERY EXECUTION
entitySelection.query( )
entitySelection.queryPath
entitySelection.queryPlan
GET QUERY DESTINATION
QUERY
SET QUERY DESTINATION
Product: 4D
Theme: ORDA - DataClass
Created: 4D v17
Modified: 4D v17 R5
Modified: 4D v17 R6
4D Language Reference ( 4D v19)
4D Language Reference ( 4D v19.1)
4D Language Reference ( 4D v19.4)
4D Language Reference ( 4D v19.5)
4D Language Reference ( 4D v19.6)
4D Language Reference ( 4D v19.7)
4D Language Reference ( 4D v19.8)