Using the latest version?
JFrog Platform User Guide
JFrog Artifactory 6.x Documentation
To get the latest version, go to the JFrog Unified Platform
Here is an another example that shows the full power of AQL to mine information from your repositories in a way that no other tool can match.
// Compare the contents of artifacts in 2 "maven+example" builds items.find( { "name":{"$match":"multi2*.jar"}, "$or":[ { "$and":[ {"artifact.module.build.name":{"$eq":"maven+example"}}, {"artifact.module.build.number":{"$eq":"317"}} ] }, { "$and":[ {"artifact.module.build.name":{"$eq":"maven+example"}}, {"artifact.module.build.number":{"$eq":"318"}} ] } ] }).include("archive.entry")
Architecture
AQL构造为一组相互关联的《婚姻保护法》ins as displayed in the diagram below. You may run queries only on one domain at a time, and this is referred to as thePrimarydomain of the query.
目前,以下是支持为主domains:Item,Build,Entry,PromotionandRelease.i.e., your queries may be of the form:items.find(...), builds.find(...),archive.entries.find(...), build.promotions.find(...) or releases.find(...).
You may use fields from other domains as part of your search criteria or to specify fields to display in the output, but in that case, you need to follow the conventions described inUsing Fields.
Supported Domains
AQL was introduced in Artifactory V3.5.0 with support forItemas a primary domain with its attachedProperty, as well asStatisticas a secondary domain. Later versions of Artifactory introduced additional domains that can be included in queries. The following table summarizes from which version each domain is accessible.
3.5.0 | 4.2.0 | 4.7.0 | 6.0.0 | |
---|---|---|---|---|
Item |
||||
Item.Property |
||||
Statistic |
||||
Archive |
||||
Archive.Entry |
||||
Artifact |
||||
Dependency |
||||
Module |
||||
Module.Property |
||||
Build |
||||
Build.Property |
||||
Promotion |
||||
Release |
||||
Release_artifact |
Usage
Syntax
.find( ).include( ).sort( ).offset( ).limit( )
where:
domain_query |
The query corresponding to the primary domain. Must be one ofitems,buildsorentries. |
criteria |
The search criteria in valid JSON format |
fields |
(Optional) There is a default set of fields for query output. This parameter lets youspecify a different set of fieldsthat should be included in the output |
order_and_fields |
(Optional) The fields on which the output should be sorted, and the sort order. A default set of fields and sort order is defined for each domain. |
num_records |
(Optional) The maximum number of records that should be extracted. If omitted, all records answering the query criteria will be extracted. |
offset |
(Optional) The offset from the first record from which to display results (i.e. how many results should be skipped for display) |
Limitation
Sort,limitandoffsetelements only work in the following cases:
- Your query does not have anincludeelement
- If you do have anincludeelement, you only specify fields from the primary domain in it.
为example, in the following query,sort,limitandoffsetwill not work because the primary domain isitem, but theincludeelementspecifies that fields from the theartifact,moduleandbuilddomains should be displayed:
items.find()其中包括(“工件”、“artifact.module”,"artifact.module.build")
Using Fields
Any fields from your primary domain can be used directly anywhere in your query. If you use fields from other domains, they must be specified using a complete relation path from the primary domain.
为example, to find all items in a repository called "myrepo" you would use:
items.find({"repo": "myrepo"})
But to find all items created by modules named "mymodule" you would use:
items.find({"artifact.module.name" : "mymodule"})
And since you may also issue a query from thebuilddomain, to find all builds that generated an item called "artifactory.war", you could also use:
builds.find({"module.artifact.item.name": "artifactory.war"})
Execution
To execute an AQL query, use theArtifactory Query Language REST API.
Output Fields
Output result will return a JSON response, with 2 fields:
- results——结果数组,根据查询请求ed domain and inclusions, with fields corresponding to the request parameter.
- range-Describes the number ofresultsreturned by the query, and consists of:
- start_pos:is the first index of the first result. should be equal to the offset. (if none provided, should be 0)
- end_pos:is the index+1 of the last result.
- total:the total number of results returned.
- limit: optional, if limit was provided
Sample output:
{ "results" : [ { "repo" : "artifactory-local", "path" : "com/jfrog/artifactory/artifactory-oss", "name" : "maven-metadata.xml", "type" : "file", "size" : 383, "created" : "2018-11-06T11:15:01.265Z", "created_by" : "admin", "modified" : "2018-11-06T11:15:01.000Z", "modified_by" : "admin", "updated" : "2018-11-06T11:15:01.267Z" } ], "range" : { "start_pos" : 0, "end_pos" : 1, "total" : 1, "limit" : 1 } }
Entities and Fields
You may issue afindrequest according to thesyntaxabove, and configure your request to display fields from any of the domains.
Domain | Field Name | Type | Description |
---|---|---|---|
item | repo | String | The name of the repository in which this item is stored |
path | String | The full path associated with this item | |
name | String | The name of the item | |
created | Date | When the item was created | |
modified | Date | File system timestamp indicating when the item was last modified | |
updated | Date | When the item was last uploaded to a repository. | |
created_by | String | The name of the item owner | |
modified_by | String | The name of the last user that modified the item | |
type | Enum | The item type (file/folder/any). If |
|
depth | int | The depth of the item in the path from the root folder | |
original_md5 | String | The item's md5 hash code when it was originally uploaded | |
actual_md5 | String | The item's current md5 hash code | |
original_sha1 | String | The item's sha1 hash code when it was originally uploaded | |
actual_sha1 | String | The item's current sha1 hash code | |
sha256 | String |
The item's sha256 hash code SHA-256 is supported from Artifactory version 5.5 You can only do an AQL search on an Artifact that has been deployed to Artifactory version 5.5 or above, or if you havemigrated your databaseas described inSHA-256 Supportafter upgrading Artifactory to version 5.5 and above. |
|
size | long | The item's size on disk | |
virtual_repos | String | The virtual repositories which contain the repository in which this item is stored. | |
archive |
The archive domain currently contains no fields |
||
entry | name | String | The entry's name |
path | String | The path of the entry within the repository | |
promotion |
created | Date | When the build was promoted |
created_by | String | The Artifactory user that promoted the build | |
status | String | The status of the promotion | |
repo | String | The name of the repository to which the build was promoted | |
comment | String | A free text comment about the promotion | |
user | String | The CI server user that promoted the build | |
build | url | String | The URL of the build |
name | String | The build name | |
number | String | The build number | |
created | Date | File system timestamp indicating when the item was last modified | |
created_by | String | The name of the user who created the build | |
modified | Date | File system timestamp indicating when the build was last modified | |
modified_by | String | The name of the last user that modified the build | |
started | Date | The build start time. The value for this field is directly taken fromthe relevant build'sbuild-info.jsonfile. The field is immutable, and does not change upon build promotion or build replication. |
|
property | key | String | The property key |
value | String | The property value | |
stat
|
downloaded | date | The last time an item was downloaded |
downloads | int | The total number of downloads for an item | |
downloaded_by | String | The name of the last user to download this item | |
remote_downloads | int | The total number of downloads for an item from a smart remote repository proxying the local repository in which the item resides | |
remote_downloaded | date | The last time an item was downloaded from a smart remote repository proxying the local repository in which the item resides | |
remote_downloaded_by | String | The name of the last user to download this item from a smart remote repository proxying the local repository in which the item resides | |
remote_origin | String | The address of the remote Artifactory instance along a smart remote proxy chain from which the download request originated. | |
remote_path | String | The full path along a smart remote proxy chain through which the download request went from the origin instance to the current instance. | |
artifact | name | String | The name of the artifact |
type | String | The type of the artifact | |
sha1 | String | The SHA1 hash code of the artifact | |
md5 | String | The MD5 hash code of the artifact | |
module | name | String | The name of the module |
dependency | name | String | The name of the dependency |
scope | String | The scope of the dependency | |
type | String | The type of the dependency | |
sha1 | String | The SHA1 hash code of the dependency | |
md5 | String | The MD5 hash code of the dependency | |
release | name | String | The name of the release bundle |
version | String | The version of the release bundle | |
status | String | The status of the release bundle | |
created | String | The date when the release bundle was created | |
signature | String | The release bundle signature | |
release_artifact | path | String | The release artifact full repo path |
Constructing Search Criteria
Thecriteriaelement must be a valid JSON format statement composed of the criteria that specify the items that should be returned. It is essentially a compound boolean statement, and only elements for which the statement evaluates totrueare returned by the query.
Each criterion is essentially a comparison statement that is applied either to a field or a property. Please see the full list ofComparison Operators. While each criterion may be expressed in complete general format, AQL defines shortened forms for readabilityas described below.
Field Criteria
The general way to specify a criterion on a field is as follows:
{"" : {" " : " "}}
If the query applied is to a different domain, then field names must be pre-pended by a relation path to the primary domain.
为example:
//Find items whose "name" field matches the expression "*test.*" items.find({"name": {"$match" : "*test.*"}}) //Find items that have been downloaded over 5 times. //We need to include the "stat" specifier in "stat.downloads" since downloads is a field of the stat domain and not of the item domain. items.find({"stat.downloads":{"$gt":"5"}}) //Find items that have never been downloaded. Note that when specifying zero downloads we use "null" instead of 0. //We need to include the "stat" specifier in "stat.downloads" since downloads is a field of the stat domain and not of the item domain. items.find({"stat.downloads":{"$eq":null}}) //Find builds that use a dependency that is a snapshot builds.find({"module.dependency.item.name":{"$match":"*SNAPSHOT*"}})
Fields with "Zero" value in the stat domain
Note that when searching for items that have a "zero" value in the stat domain, you should search for null, not 0. For example, as shown above, when searching for items with zero downloads you specify "null" instead of 0.
Short notation for Field criteria
AQL supports a short notation for search criteria on fields.
An "equals" ("$eq") criterion on a field may be specified as follows:
{"
Example |
Find items whose "name" field equals "ant-1.9.4.jar" |
Regular notation |
|
Short notation |
|
Properties Criteria
Artifactory lets you attach, and search on properties in three domains:items,modulesandbuilds.
The general way to specify a criterion on a property is as follows:
{"@":{"operator":" "}}
Accessing the right properties
如果你从主指定属性domain of your query, you may simply enter the property key and value as described above. If you are specifying properties from one of the other domains, you need to specify the full relational path to the property.
In the example below, the primary domain is thebuilddomain, but we want to find builds based a property in theitemdomain, so we must specify the full path to the property:
builds.find({"module.artifact.item.@qa_approved" : {"$ne" : "true"}})
Here are some examples:
//Find items that have been approved by QA" items.find({"@qa_approved" : {"$eq" : "true"}}) //Find builds that were run on a linux machine" builds.find({"@os" : {"$match" : "linux*"}}) //Find items that were created in a build that was run on a linux machine. items.find({"artifact.module.build.@os" : {"$match" : "linux*"}})
Short notation for properties criteria
AQL supports a short notation for search criteria on properties.
An "equals" ("$eq") criterion on a property may be specified as follows:
{"@
Example |
Find items with associated properties named "license" with a value that equals "GPL" |
Regular notation |
|
Short notation |
items.find({"@artifactory.licenses" : "GPL"}) |
Compounding Criteria
Search criteria on both fields and properties may be nested and compounded into logical expressions using "$and" or "$or" operators. If no operator is specified, the default is$and
={<"$and"|"$or">:[{ },{ }]
Criteria may be nested to any degree
Note that since search criteria can be nested to any degree, you may construct logical search criteria with any degree of complexity required.
Here are some examples:
//This example shows both an implicit "$and" operator (since this is the default, you don't have to expressly specify it, but rather separate the criteria by a comma), and an explicit "$or" operator. //Find all items that are files and are in either the jcenter or my-local repositories. items.find({"type" : "file","$or":[{"repo" : "jcenter", "repo" : "my-local" }]}) //Find all the items that were created in a build called "my_debian_build" and whose name ends with ".deb" or all items created in a build called "my_yum_build" and whose name ends with ".rpm". items.find( { "$or": [ { "$and": [ {"artifact.module.build.name" : "my_debian_build"} , {"name" : {"$match" : "*.deb"}} ] }, { "$and": [ {"artifact.module.build.name" : "my_yum_build"} , {"name" : {"$match" : "*.rpm"}} ] } ] } ) //Find all items in a repository called "my_local" that have a property with a key called "license" and value that is any variant of "LGPL". items.find({"repo" : "my_local"},{"@artifactory.licenses" : {"$match" : "*LGPL*"}})
Matching Criteria on a Single Property ($msp)
A search that specifies several criteria on properties may sometimes yield unexpected results.
This is because items are frequently annotated with several properties, and as long as any criterion is true for any property, the item will be returned in a regularfind.
But sometimes, we need to find items in which a single specific property answers several criteria. For this purpose we use the$msp (match on single property)operator.
The fundamental difference between a regularfindand using the$mspoperator is:
- findwill return an item ifANYof its properties answerALLof the criteria in the search term.
- $mspwill only return an item if at leastONEof its properties answersALLof the criteria in the$mspterm.
Here is an example.
Consider two items A and B.
A has a license property with valueAGPL-V3
B has two license properties . One isLGPL-2.1, and the otherLGPL-2.2
Now let's assume we want to find items that use any variety of GPL license as long as it's NOT LGPL-2.1.
In our example we would expect to get bothItems Aand Breturned sinceAhasAGPL-V3andBhasLGPL-2.2.
As a first thought, we might write our query as follows:
items.find({ "@license":{"$match": "*GPL*"}, "@license":{"$nmatch": "LGPL-2.1*"} })
But this query only returnsitem A.
Item A is returned because it clearly answers both criteria: "@license":{"$match": "*GPL*"} and "@license":{"$nmatch": "LGPL-2.1*"}
Item B is not returned because it has the property license=LGPL-2.1 which does not meet the criterion of "@license":{"$nmatch": "LGPL-2.1*"}.
If we use the$mspoperator as follows:
"items.find({ "$msp": [ "@license":{"$match": "*GPL*"}, "@license":{"$nmatch": "LGPL-2.1*"} ]}).
Then bothItem Aand Item Bare returned.
Item A is returned because it has the @license propertyAGPL-V3which meetsboththe {"@license":{"$match": "*GPL*"}} criterion and the "@license":{"$nmatch": "LGPL-2.1*"} criterion.
Item B is returned because it has the @license propertyLGPL-2.2which also meetsboththe{"@license":{"$match": "*GPL*"}} criterion and the "@license":{"$nmatch": "LGPL-2.1*"} criterion.
Note that the$msp
operator works equally well on all domains that have properties:item,moduleandbuild.
Comparison Operators
The following table lists the full set of comparison operators allowed:
Operator | Types | Meaning |
---|---|---|
$ne | string, date, int, long | Not equal to |
$eq | string, date, int, long | Equals |
$gt | string, date, int, long | Greater than |
$gte | string, date, int, long | Greater than or equal to |
$lt | string, date, int, long | Less than |
$lte | string, date, int, long | Less than or equal to |
$match | string | Matches |
$nmatch | string | Does not match |
为time-based operations, please also refer toRelative Time Operators.
Using Wildcards
To enable search using non-specific criteria, AQL supports wildcards in common search functions.
Using Wildcards with$matchand$nmatch
When using the "$match
" and "$nmatch
" operators, the "*" wildcard replaces any string and the "?" wildcard replaces a single character.
"Catch all" Notation on Properties
In addition to supporting "$match
" and "$nmatch
", AQL supports a notation that uses wildcards to matchanykey oranyvalue on properties.
If you specify "@*" as the property key, then it means a match on any key.
If you specify "*
" as the property value, then it means a match on any value
Example |
Find items that have any property with a value of "GPL" |
Regular notation |
|
Short notation |
|
Example |
Find any items annotated with any property whose key is "license" (i.e. find any items with a "license" property) |
Regular notation |
items.find({"$and" : [{"property.key" : {"$eq" : "license"}}, {"property.value" : {"$eq" : "*"}}]}) |
Short notation |
items.find({"@artifactory.licenses":"*"}) |
Be careful not to misuse widlcards
Wildcard characters ("*" and "?") used in queries that do not conform to the above rules are interpreted as literals.
Examples
To avoid confusion, here are some examples that use the "*" and "?" characters explaining why they are interpreted as wildcards or literals.
Query | Wildcard or Literal | Explanation | What the query returns |
---|---|---|---|
items.find ({" name ":{" $匹配”:“ant-1.9.4 *”。}}) |
Wildcard | Wildcards on fields are allowed with the |
All items whose name matches the expression "ant-1.9.4.*" |
items.find({"name":{"$eq":"ant-1.9.4.*"}}) |
Literal | Wildcards on fields are only allowed with the |
Only find items whose name is literally "ant-1.9.4.*" |
|
Wildcard | 为properties, this short notation is allowed and denotes any value |
All items with a property whose key is "license" |
|
Literal | This is the short notation replacing the $eq operator for properties, but it does not use the "catch all" notation for properties. |
All items with a license whose value is literally "*GPL" |
|
Wildcard | Wildcards on properties are allowed with the$match operator. |
All items with a license matches the expression "*GPL*" |
Date and Time Format
AQL supports Date and Time formats according to aW3C profileof the ISO 8601 Standard for Date and Time Formats.
The complete date and time notation is specified as:
YYYY-MM-DDThh:mm:ss.sTZD (e.g., 2012-07-16T19:20:30.45+01:00)
Date/Time specified in partial precision is also supported: (i.e. specify just the year, or year and month, year, month and day etc.)
为example, the following query will return all items that were modified after July 16, 2012 at 30.45 seconds after 7:20pm at GMT+1 time zone:
//Find all the items that have been modified after 2012-07-16T19:20:30.45+01:00 items.find({"modified" : {"$gt" : "2012-07-16T19:20:30.45+01:00"}}) //Find all the builds that have were created after 2012-07-01 builds.find({"created" : {"$gt" : "2012-07-01"}})
为full details, please refer to theW3C documentation.
Relative Time Operators
AQL supports specifying time intervals for queries using relative time. In other words, the time interval for the query will always be relative to the time that the query is run, so you don't have to change or formulate the time period, in some other way, each time the query is run. For example, you may want to run a query over the last day, or for the time period up to two weeks ago.
Relative time is specified using the following two operators:
$before |
The query is run over complete period up to specified time. |
$last |
The query is run over period from the specified time until the query is run |
Time periods are specified with a number and one of the following suffixes:
milliseconds |
"mills", "ms" |
seconds |
"seconds", "s" |
minutes |
"minutes" |
days |
"days", "d" |
weeks |
"weeks", "w" |
months |
"months", "mo" |
years |
"years", "y" |
为example, to specify five days, you could use "5d". To specify two weeks, you could use "2w".
Below are some examples using relative time operators:
//Find all the items that were modified during the last three days items.find({"modified" : {"$last" : "3d"}}) //Find all the builds that were created up to two weeks ago (i.e. no later than two weeks ago) builds.find({"created" : {"$before" : "2w"}})
Specifying Output Fields
Each query displays a default set of fields in the result set, however you have complete control this and may specify which fields to display using an optionalincludeelement in your query.
You can even specify to display fields from other entities related to your result set.
Displaying All Fields
Use:.include("*")
为example:
//Find all items, and display all the item fields items.find().include("*")
Displaying Specific Fields
Each query displays a default set of fields in the output. Using the.include
element you can override this default setting and specify any particular set of fields you want to receive in the output.
Use:.include("
为example:
//Find all items, only display the "name" and "repo" fields items.find().include("name", "repo")
You can also display specific fields from other entities associated with those returned by the query.
If you specify any field from theitemdomain, then this will override the default output setting, and only theitemfields you expressly specified will be displayed.
If you only specify fields from thepropertyorstatdomains, then the output will display the default fields from theitemdomain, and in addition, the other fields you expressly specified from thepropertyorstatdomains.
为example:
//Find all items, and display the "name" and "repo" fields as well as the number of "downloads" from the corresponding "stat" entity items.find().include("name", "repo", "stat.downloads") //Find all items, and display the default item fields fields as well as the stat fields items.find().include("stat") //Find all items, and display the default item fields as well as the stat and the property fields items.find().include("stat", "property") //Find all items, and display the "name" and "repo" fields as well as the stat fields items.find().include("name", "repo", "stat") //Find all builds that generated items with an Apache license, and display the build fields as well as the item "name" fields. Click below to view the output of this query builds.find({ "module.artifact.item.@license":{"$match":"Apache*"} } ).include("module.artifact.item.name")
Users Without Admin Privileges
To ensure that non-privileged users do not gain access to information without the right permissions, users without admin privileges have the following restrictions:
- The primary domain in the query may only beitem.
- The following three fields must be included in the
include
directive:name, repo
, andpath
.
Note, however, that once these restrictions are met, you may include any other accessible field from any domain intheinclude
directive.
Filtering Properties by Key
As described above, the primary use of the .include element is to specify output fields to display in the result set.
This notion is applied in a similar way in regard to properties. Each item may be annotated with several (even many) properties. In many cases you may only be interested in a specific subset of the properties, and only want to display those.
So the .includeelement can be used to filter out unwanted properties from the result, and only display (i.e. "include") those you are interested in.
为example, to display all the properties annotating an item found :
//Find all items, and display the "name" and "repo" fields, as well as all properties associated with each item items.find().include("name", "repo", "property.*")
However, if you are only interested in a specific property (e.g. you just want to know the version of each item returned), you can filter out all other properties and only include the property with the key you are interested in:
//Find all items, and display the "name" and "repo" fields, as well as the key and value of the "version" property of each item items.find().include("name", "repo", "@version")
Sorting
AQL implements a default sort order, however, you can override the default and specify any other sort order using fields in your output by adding the.sort
element to the end of your query as follows:
.sort({"<$asc | $desc>" : ["
You can only specify sorting on fields that are displayed in the output (whether they are those displayed by default or due to a.include
element).
Here are some examples:
// Find all the jars in artifactory and sort them by repo and name items.find({"name" : {"$match":"*.jar"}}).sort({"$asc" : ["repo","name"]}) // Find all the jars in artifactory and their properties, then sort them by repo and name items.find({"name" : {"$match":"*.jar"}}).include("@").sort({"$asc" : ["repo","name"]})
Display Limits and Pagination
Limitation
Note the important limitation onsort, limitandoffsetdescribed above.
Using the.limitelements, you can limit the number of records that will be displayed by your query.
// Find all the jars in artifactory and sort them by repo and name, but only display the first 100 results items.find({"name" : {"$match":"*.jar"}).sort({"$asc" : ["repo","name"]}).limit(100)
You can also implement pagination when you want to focus on a subset of your results using the.offsetelement.
//Run the same example, but this time, display up to 50 items but skipping the first 100 items.find({"name" : {"$match":"*.jar"}).sort({"$asc" : ["repo","name"]}).offset(100).limit(50)
Working With Virtual Repositories
From version 4.8.1, AQL supports virtual repositories. Since virtual repositories only contain items indirectly through the local repositories they include, several conventions have been laid down as described in the following sections.
Filtering on a Virtual Repository
You may limit queries to search in a specified virtual repository. In practice this means that the query will be applied to local repositories and remote repository caches included in the specified virtual repository.
为example, find all the items within any repository contained in a virtual repository called "my-virtual":
items.find({"repo" : "my-virtual"})
Output Fields
Theitemdomain has avirtual_reposfield which includes the virtual repositories in which a found item is contained. In general, to display this field, you need to expressly specify it in your query as anoutput field. However, if your query specifies a virtual repository as its search target, thevirtual_reposfield is implicitly included in the search results as an output field.
An item must be accessible in order to be found
A search query will only find an item in a virtual repository if it is accessible by that virtual repository. For example, the local repository that contains an item may specify andinclude or exclude patternwhich prevents access to the item by the encapsulating virtual repository. In this case the search query will not find the item.