Maven Central Repositoryに検索のAPIがあるのはなんとなく把握していたのですが、これまで使ったことがなかったので
ちょっと試してみようかと思いまして。
APIについてのドキュメントは、こちら。
Bookmarkable URLsと、REST APIについて書いてあります。
というか、このドキュメント、ここにリンクがあったんですね。
全然気付いていませんでした…。
検索してみる
ドキュメントに書かれている、REST APIのエンドポイントのURL(http://search.maven.org/solrsearch/select)や説明を見ていると
なんとなくわかるのですが、検索にはApache Solrが使われていますね。
REST API
These URLs allow you to access the search functionality of the Central Repository from any non-browser user agent. Note that the "wt" param- eter present in every URL determines the format of the results. Setting "wt" equal to "json" will provide a JSON response, while setting "wt" equal to "xml" will provide the same response formatted as an XML document. Another common parameter is "rows," which limits the number of results returned by the server.NOTE: Most of the URLs in this document have been URL-decoded for the sake of readability. They should work when pasted into a web browser, but you may have to URL-encode them to function when called programmatically.
http://search.maven.org/#api
Apache Solrのドキュメントは、こちら。
Common Query Parameters | Apache Solr Reference Guide 7.2
The Standard Query Parser | Apache Solr Reference Guide 7.2
ちょっと試してみましょう。
キーワード「junit」で検索。
$ curl 'http://search.maven.org/solrsearch/select?q=junit&rows=20&wt=json' {"responseHeader":{"status":0,"QTime":0,"params":{"q":"junit","defType":"dismax","indent":"off","spellcheck":"true","qf":"text^20 g^5 a^10","fl":"id,g,a,latestVersion,p,ec,repositoryId,text,timestamp,versionCount","spellcheck.count":"5","sort":"score desc,timestamp desc,g asc,a asc","rows":"20","wt":"json","version":"2.2"}},"response":{"numFound":855,"start":0,"docs":[{"id":"org.robolectric:junit","g":"org.robolectric","a":"junit","latestVersion":"3.8","repositoryId":"central","p":"jar","timestamp":1521228515000,"versionCount":15,"text":["org.robolectric","junit","-sources.jar","-javadoc.jar",".jar",".pom"],"ec":["-sources.jar","-javadoc.jar",".jar",".pom"]},{"id":"com.jslsolucoes:junit","g":"com.jslsolucoes","a":"junit","latestVersion":"1.0.0","repositoryId":"central","p":"jar","timestamp":1517374779000,"versionCount":1,"text":["com.jslsolucoes","junit","-javadoc.jar","-sources.jar",".jar",".pom"],"ec":["-javadoc.jar","-sources.jar",".jar",".pom"]},{"id":"com.google.monitoring-client:junit","g":"com.google.monitoring-client","a":"junit","latestVersion":"1.0.2","repositoryId":"central","p":"jar","timestamp":1513901021000,"versionCount":2,"text":["com.google.monitoring-client","junit","-javadoc.jar","-sources.jar",".jar",".pom"],"ec":["-javadoc.jar","-sources.jar",".jar",".pom"]},{"id":"io.github.kvlabs.filemock:junit","g":"io.github.kvlabs.filemock","a":"junit","latestVersion":"1.0.0","repositoryId":"central","p":"jar","timestamp":1513756503000,"versionCount":1,"text":["io.github.kvlabs.filemock","junit","-javadoc.jar","-sources.jar",".jar",".pom"],"ec":["-javadoc.jar","-sources.jar",".jar",".pom"]},{"id":"com.airbnb.okreplay:junit","g":"com.airbnb.okreplay","a":"junit","latestVersion":"1.4.0","repositoryId":"central","p":"jar","timestamp":1513032811000,"versionCount":4,"text":["com.airbnb.okreplay","junit","-sources.jar","-javadoc.jar",".jar",".pom"],"ec":["-sources.jar","-javadoc.jar",".jar",".pom"]},{"id":"com.buschmais.jqassistant.plugin:junit","g":"com.buschmais.jqassistant.plugin","a":"junit","latestVersion":"1.3","repositoryId":"central","p":"jar","timestamp":1494449996000,"versionCount":3,"text":["com.buschmais.jqassistant.plugin","junit","-asciidoc.zip","-sources.jar","-javadoc.jar",".jar",".pom"],"ec":["-asciidoc.zip","-sources.jar","-javadoc.jar",".jar",".pom"]},{"id":"com.airbnb.walkman:junit","g":"com.airbnb.walkman","a":"junit","latestVersion":"1.0.3","repositoryId":"central","p":"jar","timestamp":1489710404000,"versionCount":1,"text":["com.airbnb.walkman","junit","-sources.jar","-javadoc.jar",".jar",".pom"],"ec":["-sources.jar","-javadoc.jar",".jar",".pom"]},{"id":"com.fitbur.testify.junit:junit","g":"com.fitbur.testify.junit","a":"junit","latestVersion":"0.1.3","repositoryId":"central","p":"pom","timestamp":1455810137000,"versionCount":13,"text":["com.fitbur.testify.junit","junit",".pom"],"ec":[".pom"]},{"id":"org.typelevel:junit","g":"org.typelevel","a":"junit","latestVersion":"2.11.7","repositoryId":"central","p":"jar","timestamp":1442763306000,"versionCount":1,"text":["org.typelevel","junit","-javadoc.jar","-sources.jar",".jar",".pom"],"ec":["-javadoc.jar","-sources.jar",".jar",".pom"]},{"id":"com.github.adedayo.intellij.sdk:junit","g":"com.github.adedayo.intellij.sdk","a":"junit","latestVersion":"142.1","repositoryId":"central","p":"jar","timestamp":1436806100000,"versionCount":1,"text":["com.github.adedayo.intellij.sdk","junit","-javadoc.jar","-sources.jar",".jar",".pom"],"ec":["-javadoc.jar","-sources.jar",".jar",".pom"]},{"id":"junit:junit","g":"junit","a":"junit","latestVersion":"4.12","repositoryId":"central","p":"jar","timestamp":1417709863000,"versionCount":24,"text":["junit","junit","-javadoc.jar","-sources.jar",".jar",".pom"],"ec":["-javadoc.jar","-sources.jar",".jar",".pom"]},{"id":"org.technbolts:junit","g":"org.technbolts","a":"junit","latestVersion":"1.0.1","repositoryId":"central","p":"jar","timestamp":1400104795000,"versionCount":1,"text":["org.technbolts","junit","-sources.jar","-javadoc.jar",".jar",".pom"],"ec":["-sources.jar","-javadoc.jar",".jar",".pom"]},{"id":"com.groupon.roboremote.roboremoteclient:junit","g":"com.groupon.roboremote.roboremoteclient","a":"junit","latestVersion":"0.4","repositoryId":"central","p":"jar","timestamp":1357673275000,"versionCount":3,"text":["com.groupon.roboremote.roboremoteclient","junit","-javadoc.jar","-sources.jar",".jar",".pom"],"ec":["-javadoc.jar","-sources.jar",".jar",".pom"]},{"id":"org.apache.tuscany.sca.samples:junit","g":"org.apache.tuscany.sca.samples","a":"junit","latestVersion":"2.0","repositoryId":"central","p":"jar","timestamp":1340054060000,"versionCount":1,"text":["org.apache.tuscany.sca.samples","junit","-sources.jar",".jar",".pom"],"ec":["-sources.jar",".jar",".pom"]},{"id":"org.apache.isis.viewer:junit","g":"org.apache.isis.viewer","a":"junit","latestVersion":"0.2.0-incubating","repositoryId":"central","p":"jar","timestamp":1328874364000,"versionCount":2,"text":["org.apache.isis.viewer","junit","-site.xml","-sources.jar","-javadoc.jar","-test-sources.jar","-tests.jar",".jar",".pom"],"ec":["-site.xml","-sources.jar","-javadoc.jar","-test-sources.jar","-tests.jar",".jar",".pom"]},{"id":"com.kenai.nbpwr:junit","g":"com.kenai.nbpwr","a":"junit","latestVersion":"4.7-201002241900","repositoryId":"central","p":"nbm","timestamp":1267178357000,"versionCount":1,"text":["com.kenai.nbpwr","junit",".jar","-tests.jar",".nbm",".pom"],"ec":[".jar","-tests.jar",".nbm",".pom"]},{"id":"org.mod4j.org:junit","g":"org.mod4j.org","a":"junit","latestVersion":"3.8.2","repositoryId":"central","p":"jar","timestamp":1250247739000,"versionCount":1,"text":["org.mod4j.org","junit",".jar",".pom"],"ec":[".jar",".pom"]},{"id":"org.codehaus.mevenide:junit","g":"org.codehaus.mevenide","a":"junit","latestVersion":"3.1.4","repositoryId":"central","p":"nbm","timestamp":1217940118000,"versionCount":5,"text":["org.codehaus.mevenide","junit","-javadoc.jar","-sources.jar",".jar",".nbm",".pom"],"ec":["-javadoc.jar","-sources.jar",".jar",".nbm",".pom"]},{"id":"org.eclipse.jdt:junit","g":"org.eclipse.jdt","a":"junit","latestVersion":"3.3.0-v20070606-0010","repositoryId":"central","p":"jar","timestamp":1196147709000,"versionCount":2,"text":["org.eclipse.jdt","junit",".jar",".pom"],"ec":[".jar",".pom"]},{"id":"junit:junit-dep","g":"junit","a":"junit-dep","latestVersion":"4.11","repositoryId":"central","p":"pom","timestamp":1352920913000,"versionCount":11,"text":["junit","junit-dep",".pom"],"ec":[".pom"]}]},"spellcheck":{"suggestions":[]}}
すごい長いんですけど、なんか検索できました。
ちなみに、「wt=json」を省略してもJSONで返ってきます。rowsは1度に返ってくるドキュメント数で、省略するとデフォルトの10ドキュメントが返ってくるようです。
$ curl 'http://search.maven.org/solrsearch/select?q=junit' {"responseHeader":{"status":0,"QTime":0,"params":{"q":"junit","defType":"dismax","indent":"off","spellcheck":"true","qf":"text^20 g^5 a^10","fl":"id,g,a,latestVersion,p,ec,repositoryId,text,timestamp,versionCount","spellcheck.count":"5","sort":"score desc,timestamp desc,g asc,a asc","version":"2.2","wt":"json"}},"response":{"numFound":855,"start":0,"docs":[{"id":"org.robolectric:junit","g":"org.robolectric","a":"junit","latestVersion":"3.8","repositoryId":"central","p":"jar","timestamp":1521228515000,"versionCount":15,"text":["org.robolectric","junit","-sources.jar","-javadoc.jar",".jar",".pom"],"ec":["-sources.jar","-javadoc.jar",".jar",".pom"]},{"id":"com.jslsolucoes:junit","g":"com.jslsolucoes","a":"junit","latestVersion":"1.0.0","repositoryId":"central","p":"jar","timestamp":1517374779000,"versionCount":1,"text":["com.jslsolucoes","junit","-javadoc.jar","-sources.jar",".jar",".pom"],"ec":["-javadoc.jar","-sources.jar",".jar",".pom"]},{"id":"com.google.monitoring-client:junit","g":"com.google.monitoring-client","a":"junit","latestVersion":"1.0.2","repositoryId":"central","p":"jar","timestamp":1513901021000,"versionCount":2,"text":["com.google.monitoring-client","junit","-javadoc.jar","-sources.jar",".jar",".pom"],"ec":["-javadoc.jar","-sources.jar",".jar",".pom"]},{"id":"io.github.kvlabs.filemock:junit","g":"io.github.kvlabs.filemock","a":"junit","latestVersion":"1.0.0","repositoryId":"central","p":"jar","timestamp":1513756503000,"versionCount":1,"text":["io.github.kvlabs.filemock","junit","-javadoc.jar","-sources.jar",".jar",".pom"],"ec":["-javadoc.jar","-sources.jar",".jar",".pom"]},{"id":"com.airbnb.okreplay:junit","g":"com.airbnb.okreplay","a":"junit","latestVersion":"1.4.0","repositoryId":"central","p":"jar","timestamp":1513032811000,"versionCount":4,"text":["com.airbnb.okreplay","junit","-sources.jar","-javadoc.jar",".jar",".pom"],"ec":["-sources.jar","-javadoc.jar",".jar",".pom"]},{"id":"com.buschmais.jqassistant.plugin:junit","g":"com.buschmais.jqassistant.plugin","a":"junit","latestVersion":"1.3","repositoryId":"central","p":"jar","timestamp":1494449996000,"versionCount":3,"text":["com.buschmais.jqassistant.plugin","junit","-asciidoc.zip","-sources.jar","-javadoc.jar",".jar",".pom"],"ec":["-asciidoc.zip","-sources.jar","-javadoc.jar",".jar",".pom"]},{"id":"com.airbnb.walkman:junit","g":"com.airbnb.walkman","a":"junit","latestVersion":"1.0.3","repositoryId":"central","p":"jar","timestamp":1489710404000,"versionCount":1,"text":["com.airbnb.walkman","junit","-sources.jar","-javadoc.jar",".jar",".pom"],"ec":["-sources.jar","-javadoc.jar",".jar",".pom"]},{"id":"com.fitbur.testify.junit:junit","g":"com.fitbur.testify.junit","a":"junit","latestVersion":"0.1.3","repositoryId":"central","p":"pom","timestamp":1455810137000,"versionCount":13,"text":["com.fitbur.testify.junit","junit",".pom"],"ec":[".pom"]},{"id":"org.typelevel:junit","g":"org.typelevel","a":"junit","latestVersion":"2.11.7","repositoryId":"central","p":"jar","timestamp":1442763306000,"versionCount":1,"text":["org.typelevel","junit","-javadoc.jar","-sources.jar",".jar",".pom"],"ec":["-javadoc.jar","-sources.jar",".jar",".pom"]},{"id":"com.github.adedayo.intellij.sdk:junit","g":"com.github.adedayo.intellij.sdk","a":"junit","latestVersion":"142.1","repositoryId":"central","p":"jar","timestamp":1436806100000,"versionCount":1,"text":["com.github.adedayo.intellij.sdk","junit","-javadoc.jar","-sources.jar",".jar",".pom"],"ec":["-javadoc.jar","-sources.jar",".jar",".pom"]}]},"spellcheck":{"suggestions":[]}}
見づらいので、jqあたりをはさんでみるとよい?
$ curl -s 'http://search.maven.org/solrsearch/select?q=junit' | jq
クエリに使えるフィールドの名前は、REST APIのサンプルのところに書かれています。
Mimics searching by coordinate in Advanced Search. This search uses all coordinates ("g" for groupId, "a" for artifactId, "v" for version, "p" for packaging, "l" for classifier) and uses "AND" to require all terms by default. Only one term is required for the search to work. Terms can also be connected by "OR" separated to make them optional.
http://search.maven.org/#api
- g … groupId
- a … artifactId
- v … version
- p … packaging
- l … classfier
それほど、想像に難くありませんね?「classfier」だけは、ちょっと予想外かもですが。
あとは…
- fc … fully-qualified classname in Advanced Search
- tags
- 1 … SHA-1 Checksum
tags?
確認。
*情報量が多いので、表示するフィールドを絞っています
$ curl -s 'http://search.maven.org/solrsearch/select?q=g:junit' | jq '.response.docs[] | {id, g, latestVersion}' { "id": "junit:junit", "g": "junit", "latestVersion": "4.12" } { "id": "junit:junit-dep", "g": "junit", "latestVersion": "4.11" }
OR検索。
$ curl -s 'http://search.maven.org/solrsearch/select?q=g:org.junit.*+OR+a:junit-platform*' | jq '.response.docs[] | {id, g, latestVersion}' { "id": "org.junit.platform:junit-platform-surefire-provider", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-suite-api", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-runner", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-launcher", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-gradle-plugin", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-engine", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-console-standalone", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-console", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-commons", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.vintage:junit-vintage-engine", "g": "org.junit.vintage", "latestVersion": "5.1.0" }
AND検索。
$ curl -s 'http://search.maven.org/solrsearch/select?q=g:org.junit.*+AND+a:junit-platform*' | jq '.response.docs[] | {id, g, latestVersion}' { "id": "org.junit.platform:junit-platform-surefire-provider", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-suite-api", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-runner", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-launcher", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-gradle-plugin", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-engine", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-console-standalone", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-console", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-commons", "g": "org.junit.platform", "latestVersion": "1.1.0" }
まあ、デフォルトはANDっぽいです。
$ curl -s 'http://search.maven.org/solrsearch/select?q=g:org.junit.*+a:junit-platform*' | jq '.response.docs[] | {id, g, latestVersion}' { "id": "org.junit.platform:junit-platform-surefire-provider", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-suite-api", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-runner", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-launcher", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-gradle-plugin", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-engine", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-console-standalone", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-console", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-commons", "g": "org.junit.platform", "latestVersion": "1.1.0" }
また、groupIdとartifactIdを指定した時に、「core=gav」を付与すると、全バージョンを取得することができます。
確認。
$ curl -s 'http://search.maven.org/solrsearch/select?q=g:org.junit.jupiter+a:junit-jupiter-api&core=gav' | jq '.response.docs[] | {id, g, v}'{ "id": "org.junit.jupiter:junit-jupiter-api:5.1.0", "g": "org.junit.jupiter", "v": "5.1.0" } { "id": "org.junit.jupiter:junit-jupiter-api:5.1.0-RC1", "g": "org.junit.jupiter", "v": "5.1.0-RC1" } { "id": "org.junit.jupiter:junit-jupiter-api:5.1.0-M2", "g": "org.junit.jupiter", "v": "5.1.0-M2" } { "id": "org.junit.jupiter:junit-jupiter-api:5.0.3", "g": "org.junit.jupiter", "v": "5.0.3" } { "id": "org.junit.jupiter:junit-jupiter-api:5.1.0-M1", "g": "org.junit.jupiter", "v": "5.1.0-M1" } { "id": "org.junit.jupiter:junit-jupiter-api:5.0.2", "g": "org.junit.jupiter", "v": "5.0.2" } { "id": "org.junit.jupiter:junit-jupiter-api:5.0.1", "g": "org.junit.jupiter", "v": "5.0.1" } { "id": "org.junit.jupiter:junit-jupiter-api:5.0.0", "g": "org.junit.jupiter", "v": "5.0.0" } { "id": "org.junit.jupiter:junit-jupiter-api:5.0.0-RC3", "g": "org.junit.jupiter", "v": "5.0.0-RC3" } { "id": "org.junit.jupiter:junit-jupiter-api:5.0.0-RC2", "g": "org.junit.jupiter", "v": "5.0.0-RC2" }
件数が多い時のページ送りは、startで。
*rowsを5で絞っています
## 1ページ目(デフォルト、start=0) $ curl -s 'http://search.maven.org/solrsearch/select?q=g:org.junit.*&rows=5' | jq '.response.docs[] | {id, g, latestVersion}' { "id": "org.junit.vintage:junit-vintage-engine", "g": "org.junit.vintage", "latestVersion": "5.1.0" } { "id": "org.junit.platform:junit-platform-surefire-provider", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-suite-api", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-runner", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-launcher", "g": "org.junit.platform", "latestVersion": "1.1.0" } ## 2ページ目(start=5) $ curl -s 'http://search.maven.org/solrsearch/select?q=g:org.junit.*&rows=5&start=5' | jq '.response.docs[] | {id, g, latestVersion}' { "id": "org.junit.platform:junit-platform-gradle-plugin", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-engine", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-console-standalone", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-console", "g": "org.junit.platform", "latestVersion": "1.1.0" } { "id": "org.junit.platform:junit-platform-commons", "g": "org.junit.platform", "latestVersion": "1.1.0" } ## 3ページ目(start=10) $ curl -s 'http://search.maven.org/solrsearch/select?q=g:org.junit.*&rows=5&start=10' | jq '.response.docs[] | {id, g, latestVersion}' { "id": "org.junit.jupiter:junit-jupiter-params", "g": "org.junit.jupiter", "latestVersion": "5.1.0" } { "id": "org.junit.jupiter:junit-jupiter-migrationsupport", "g": "org.junit.jupiter", "latestVersion": "5.1.0" } { "id": "org.junit.jupiter:junit-jupiter-engine", "g": "org.junit.jupiter", "latestVersion": "5.1.0" } { "id": "org.junit.jupiter:junit-jupiter-api", "g": "org.junit.jupiter", "latestVersion": "5.1.0" } { "id": "org.junit.jupiter:junit-jupiter-migration-support", "g": "org.junit.jupiter", "latestVersion": "5.0.0-M4" }
なお、対象のファイルをダウンロードする時は、
http://search.maven.org/remotecontent?filepath=[groupId]/[artifactId]/[version]/[artifactId]-[version].[package]
例)
http://search.maven.org/remotecontent?filepath=com/jolira/guice/3.0.0/guice-3.0.0.pom
という感じですね。
とりあえず、このあたりが分かれば使い方としては十分でしょうか?