{"id":13604784,"url":"https://github.com/ravendb/samples-jvm","last_synced_at":"2026-02-17T05:33:41.224Z","repository":{"id":48884806,"uuid":"181500814","full_name":"ravendb/samples-jvm","owner":"ravendb","description":null,"archived":false,"fork":false,"pushed_at":"2022-11-29T12:42:15.000Z","size":1217,"stargazers_count":1,"open_issues_count":0,"forks_count":3,"subscribers_count":19,"default_branch":"hospital","last_synced_at":"2025-04-09T16:13:56.185Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ravendb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-04-15T14:11:04.000Z","updated_at":"2022-12-14T22:59:39.000Z","dependencies_parsed_at":"2023-01-22T01:16:36.721Z","dependency_job_id":null,"html_url":"https://github.com/ravendb/samples-jvm","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ravendb/samples-jvm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ravendb%2Fsamples-jvm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ravendb%2Fsamples-jvm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ravendb%2Fsamples-jvm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ravendb%2Fsamples-jvm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ravendb","download_url":"https://codeload.github.com/ravendb/samples-jvm/tar.gz/refs/heads/hospital","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ravendb%2Fsamples-jvm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29534977,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-17T05:00:25.817Z","status":"ssl_error","status_checked_at":"2026-02-17T04:57:16.126Z","response_time":100,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T19:00:51.244Z","updated_at":"2026-02-17T05:33:41.209Z","avatar_url":"https://github.com/ravendb.png","language":"Java","funding_links":[],"categories":["Languages"],"sub_categories":["JVM"],"readme":"# RavenDB JVM Client Tutorial  \n[RavenDB](ravendb.net) is a lightning fast #NoSQL document database. It's fully ACID, high-availability, \nmulti-platform, and open-source. It supports clients in a variety of programming languages including Java.  \n\nThis tutorial is a quick introduction to RavenDB and the JVM Client API. As you'll see, RavenDB is very easy to deploy and \nadminister. We will be looking at a simple demo hospital management app as an example.  \n\nThe demo app was built using the [Vaadin Flow](https://vaadin.com/flow) framework, which allows you to develop web apps \nusing only Java.  \n\nContents:\n* [How to Install RavenDB Community Edition](./README.md#how-to-install-ravendb-community-edition)\n* [How to Run the Demo](./README.md#how-to-run-the-demo)\n* [Entities as Documents](./README.md#entities-as-documents)\n* [Document Store](./README.md#document-store)\n* [Session and Unit of Work Pattern](./README.md#session-and-unit-of-work-pattern)\n* [CRUD operations](./README.md#crud-operations)\n* [Paging on large record sets](./README.md#paging-through-large-record-sets)\n* [BLOB handling - attachments](./README.md#blob-handling---attachments)\n* [Queries](./README.md#queries)\n\n## How to Install RavenDB Community Edition  \n\n1. [Register a free community license](https://ravendb.net/buy)  \n2. [Download and unzip the RavenDB version 4.x server package](https://ravendb.net/download) (the latest stable version)  \n3. From command line, run the `.\\run.ps1` script found in the package root (or `.\\setup-as-service.ps1` to launch as a service)  \n4. Once installed, the [Setup Wizard](https://ravendb.net/docs/article-page/4.2/java/start/installation/setup-wizard) will\nlaunch on a browser and prompt you to choose a security mode. \"Unsecured\" mode is appropriate for local development and for\nthe purposes of this tutorial.\n\n![Setup security](/screenshots/setup_security.png)\n\n5. Leave the other options on default. At the end of the Setup Wizard, you'll be prompted to restart \nthe server. Once you do, the [RavenDB Management Studio](https://ravendb.net/docs/article-page/4.2/java/studio/overview) \nwill launch on `localhost:8080`. (The Studio is always available at the designated http port while a Server instance is running. \nYou can also access the Studio from  the Server's command line interface with command `openbrowser`)  \n\n6. Once in the Studio, open the `About` tab to register your license:\n\n![Register License](/screenshots/manage-license-1.png)\n\nMore detailed installation and setup instructions can be found in [RavenDB's online documentation](https://ravendb.net/docs/article-page/4.2/java/start/getting-started).  \n\n## How to run the demo\n1. Fetch the code sources for this project with:  \n```\n$ git clone https://github.com/ravendb/ravendb-jvm-tutorials.git\n```\n2. From the Studio, click on the `Database` tab and create a new database with the name \"Hospital\".  \n3. Populate this database by going to `Settings` \u003e `Import Data` and importing the file `Hospital.ravendbdump` found in \nthe project root:  \n\n![Import Data](/screenshots/ravendbdump.png)\n\n4. For quick and easy testing, we recommend launching the app on a jetty server. The maven jetty plugin is already included \nin `pom.xml`. In your IDE, create a new maven run configuration and set `jetty:run` as the goal.  \n\nWhen run, the web app will be available at `http://localhost:8889/`:\n![App Homepage](/screenshots/p_home.png)  \n\n### Demo Folder Structure  \nThis app implements the [Model-View-Presenter pattern](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter).\nThe `model` folder contains the type definitions of the entities that we will be storing on the server, plus some miscellaneous \ntypes. The `view` folder contains the Vaadin components and layouts. The `presenter` folder contains the presenters \nwhich are responsible for communication with the RavenDB server.  \n\n## Entities as Documents\nAs a NoSQL (or non-relational) database, RavenDB doesn’t represent entities as rows in a table with a rigid schema. \nInstead, it represents them as _\"documents\"_ with no constraints on their structure. Similar documents are grouped in \n_collections_. Each document contains data, a unique id, and metadata in JSON format.  \n\nThe model for this demo consists of 3 main entities: _Patients_, _Doctors_, _Conditions_. There are also _Visits_, \nappointments between one doctor and one patient. Visits are embedded as an array within the corresponding patient entity. \nThese three entity types are represented by three collections of documents on the Server.\n\n![UML Diagram](/screenshots/uml.png)\n\nBelow are the type definitions of these entities on the Client side (getters and setters are omitted for brevity), accompanied by \nexamples of specific documents in JSON.  \n\n\u003cdetails\u003e\u003csummary\u003eClick to expand POJOs and documents\u003c/summary\u003e\n1. The Patient entity:  \n\n```java\npublic class Patient {\n    private String id;\n    private String firstName,lastName;\n    private Date birthDate;\n    private Gender gender;\n\n    private String email;\n    private Address address;\n    private List\u003cVisit\u003e visits;\n}\n```\nA JSON document of an example Patient containing an array of Visits:  \n\n```JSON\n{\n    \"firstName\": \"Megi\",\n    \"lastName\": \"Devasko\",\n    \"birthDate\": \"2016-11-30T22:00:00.0000000Z\",\n    \"gender\": \"FEMALE\",\n    \"email\": \"sss@box.com\",\n    \"address\": null,\n    \"visits\": [\n        {\n            \"date\": \"2019-02-26T22:00:00.0000000Z\",\n            \"doctorId\": \"doctors/1-A\",\n            \"type\": \"HOUSE\",\n            \"visitSummary\": \"just a minor pain\",\n            \"conditionId\": \"conditions/1-A\",\n            \"doctorName\": \"Dr. Megan Austin\"\n        },\n        {\n            \"date\": \"2019-01-31T22:00:00.0000000Z\",\n            \"doctorId\": \"doctors/2-A\",\n            \"type\": \"EMERGENCY ROOM\",\n            \"visitSummary\": \"nothing to worry about\",\n            \"conditionId\": \"conditions/2-A\",\n            \"doctorName\": \"Dr. Megalo Karimov\"\n        }\n    ],\n    \"@metadata\": {\n        \"@collection\": \"Patients\",\n        \"@flags\": \"HasAttachments\",\n        \"@id\": \"patients/33-A\",\n        \"Raven-Java-Type\": \"net.ravendb.demo.model.Patient\"\n    }\n}\n```\n2. Visit entity:  \n```java\npublic class Visit {\n    private Date date;\n    private String doctorId;\n    private Type type;\n    private String visitSummary;\n    private String conditionId;\n    private String doctorName;\n}\n```\nOn the server side this entity is represented as an array within a Patient document - see example Patient above.  \n\n3. Condition entity:  \n```java\npublic class Condition {\n    private String id;\n    private String name;\n    private String symptoms;\n    private String recommendedTreatment;\n}\n```\nExample Condition:  \n```JSON\n{\n    \"name\": \"Diabetes\",\n    \"symptoms\": \"swollen legs, impaired eyesight\",\n    \"recommendedTreatment\": \"sugar-free diet\",\n    \"@metadata\": {\n        \"@collection\": \"Conditions\",\n        \"@id\": \"conditions/6-A\",\n        \"Raven-Java-Type\": \"net.ravendb.demo.model.Condition\"\n    }\n}\n```\n\n4. Doctor entity:  \n```java\npublic class Doctor {\n    private String id;\n    private String name;\n    private String department;\n    private int age;\n}\n```\nExample Doctor:  \n```JSON\n{\n    \"name\": \"Sergiz Ovesian\",\n    \"department\": \"LV\",\n    \"age\": 45,\n    \"@metadata\": {\n        \"@collection\": \"Doctors\",\n        \"@id\": \"doctors/1-A\",\n        \"Raven-Java-Type\": \"net.ravendb.demo.model.Doctor\"\n    }\n}\n```\n\u003c/details\u003e\n\nRather than picking ids for our documents, we will leave them `null`. RavenDB automatically generates \nunique and human readable ids in the format: `[collection document belongs to]/[HiLo number tag]-[RavenDB cluster node tag]`. \nThe [HiLo Algorithm](https://ravendb.net/docs/article-page/4.2/java/client-api/document-identifiers/hilo-algorithm) \nprovides the unique portion of the id. We will be using one Server - effectively a one-node cluster - and by default its tag \nis \"A\", so patient documents have the ids `patients/1-A`,  `patients/2-A` and so on.\n\n## Document Store\nThe Java Client is included as a dependency in `pom.xml`.  \n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003enet.ravendb\u003c/groupId\u003e\n    \u003cartifactId\u003eravendb\u003c/artifactId\u003e\n    \u003cversion\u003eLATEST\u003c/version\u003e\n\u003c/dependency\u003e\n```\nThe primary object of the Client API is the _Document Store_, which manages the application's connection with the Server \nand holds various configuration options. One of these options is whether to use optimistic concurrency control, which \nwe'll want to enable for this app. It is recommended that you create just one Document Store instance per application by \nusing the [singleton pattern](https://www.javaworld.com/article/2073352/core-java-simply-singleton.html) as demonstrated \nbelow:  \n```java\npublic final class RavenDBDocumentStore {\n    private static IDocumentStore store;\n\n    static {\n\n        //Create new Document Store with the url of the RavenDB Server\n        //and with `Hospital` set as the default database\n        store = new DocumentStore(new String[]{\"http://127.0.0.1:8080\"},\n                                  \"Hospital\");\n\n        //Edit the conventions to enable optimistic concurrency\n        DocumentConventions conventions = store.getConventions();\n        conventions.setUseOptimisticConcurrency(true);\n\n        store.initialize();\n    }\n\n    //Return the single Document Store instance \n    public static IDocumentStore getStore() {\n        return store;\n    }\n\n}\n```\n## Session and Unit of Work Pattern  \n\nAny operation we want to perform starts by obtaining a new _Session_ object from the Document Store.\nThe Session implements the [Unit of Work](https://martinfowler.com/eaaCatalog/unitOfWork.html)\npattern. This has several implications:  \n* The Session batches requests to the server to minimize the number of round trips over the network.  \n* The Session tracks changes for all the entities that it has either loaded from or stored to the database, and commits \nthem as an ACID transaction when `[session].saveChanges()` is called.  \n* A single document always resolves to the same instance - i.e. if we try to load a document twice, the second call \nwill load the entity from a local cache rather than going over the network.  \n\nIn this demo, sessions are created and released in response to the `attach` and `detach` events in the lifecycle of each \nof our `views` (which inherit from Vaadin's `VerticalLayout`). We create a session when we navigate to a page in our web \napp (not including the root URL, or menu page), and release it when that page is closed. Vaadin maintains page state persistence, \na feature which will help us to minimize calls to the Server.  \n\nIn the view:  \n```java\n@Override\nprotected void onAttach(AttachEvent attachEvent) {\n    presenter.openSession();\n    loadPage();\n}\n\n@Override\nprotected void onDetach(DetachEvent detachEvent) {\n    presenter.releaseSession();\n    super.onDetach(detachEvent);\n}\n```\nIn the presenter:  \n```java\npublic void openSession() {\n    if (session == null) {\n        session = RavenDBDocumentStore.getStore().openSession();\n    }\n}\n\npublic void releaseSession() {\n    session.close();\n}\n```\n## CRUD operations  \nNow we can look at how the demo app implements the basic CRUD functions for our patient data. These functions are located \nin the `PatientPresenter`, an instance of which is held by the `PatientView`.  \n\nThe **create** operation:  \n```java\npublic void create(Patient patient, ProfilePicture profilePicture) {\n\n    session.store(patient);\n    \n    //Attachment handling\n    if (profilePicture != null) {\n        session.advanced().attachments().store(patient, ATTACHMENT_NAME,\n                                               profilePicture.getInputStream());\n    }\n\n    session.saveChanges();\n}\n```\nCreates a new Patient document and uploading it to the Server. Generally documents only need `session.store()` and `session.saveChanges()`\nto be stored. In this case the patient has a profile picture which doesn't fit in JSON format, so \nit needs to be handled separately as an _attachment_. Attachments are discussed further [below](./README.md#blob-handling---attachments).  \n\nThe **update** operation:  \n```java\npublic void update(Patient patient, ProfilePicture profilePicture) throws ConcurrencyException {\n    session.store(patient);\n\n    if (profilePicture != null) {\n        session.advanced().attachments().store(patient.getId(), ATTACHMENT_NAME,\n                                               profilePicture.getInputStream());\n    }\n    \n    session.saveChanges();\n}\n```\nReceives a patient and profile picture which have already been modified and stores them, in almost the same way as `create()`.\n\nThe **delete** operation:\n```java\npublic void delete(Patient patient) {\n    session.delete(patient);\n    session.saveChanges();\n}\n```\nDeletes a given patient. `delete()` can take either an object instance, as shown here, or a document id.\n\nTo **read** documents, we simply load them from the Server using \n```java\nsession.load([patientId])\n```\n\n## Paging Through Large Record Sets\nPaging through large amounts of data is one of the most common operations in RavenDB.  \nLet's say we need to display results in batches on a lazy loading grid. In this app, the grid is configured to obtain the\ntotal amount of results to a query (to calculate the total number of pages) and then to lazily load the results in batches \nof 10 as the user navigates from page to page. We can use `statistics()` to access useful data about the query, including \nthe total number of results. For the patients grid, the corresponding attachments are also obtained and streamed into a \nbyte array.\n\n![Patient Paging](/screenshots/p_paging.png)\n\n`getPatientsList()`, with error handling omitted for brevity:\n```java\npublic Pair\u003cCollection\u003cPatientWithPicture\u003e, Integer\u003e getPatientsList(int offset, int limit, boolean order) {\n    Reference\u003cQueryStatistics\u003e statsRef = new Reference\u003c\u003e();\n    IDocumentQuery\u003cPatient\u003e query = session.query(Patient.class)\n                                           .skip(offset)\n                                           .take(limit)\n                                           .statistics(statsRef);\n\n    if (order) {\n        query.orderBy(\"birthDate\");\n    }\n\n    Collection\u003cPatient\u003e list = query.toList();\n    int totalResults = statsRef.value.getTotalResults();\n\n    Collection\u003cPatientWithPicture\u003e patientWithPictures = new ArrayList\u003c\u003e();\n}\n```\n\n## BLOB Handling - Attachments\nBinary data that cannot be stored as JSON (such as images, audio, etc.) can be associated with a document as one or more _attachments_.\nAn example are the profile pictures of Patients. This POJO represents attachments on the client side:\n```java\npublic class Attachment {\n\n    String name;\n    byte[] bytes;\n\n    public InputStream getInputStream() {\n        return new ByteArrayInputStream(bytes);\n    }\n\n    public StreamResource getStreamResource() {\n        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);\n        return new StreamResource(name, () -\u003e bis);\n    }\n}\n```\n(Getters and setters are omitted for brevity)\n\nAttachments can be loaded and edited separately from the document, which saves sending the entire attachment over the network\nevery time a document is accessed. Like documents, attachments are tracked by the Session and will be included in the same \nACID transaction as any other changes tracked by the same Session.\n\nThis method retrieves the profilePicture for a given patient document:\n```java\npublic ProfilePicture getProfilePicture(Patient patient) {\n    ProfilePicture profilePicture = new ProfilePicture();\n\n    try (CloseableAttachmentResult result = session.advanced()\n            .attachments()\n            .get(patient.getId(), ATTACHMENT_NAME)) {\n\n\n        if (result == null)\n            return null;\n        InputStream data = result.getData();\n        byte[] bytes = IOUtils.toByteArray(data);\n        profilePicture.setBytes(bytes);\n        profilePicture.setName(ATTACHMENT_NAME);\n        \n        return profilePicture;\n    } catch (IOException e) {\n        logger.log(Level.SEVERE, \"\", e);\n    }\n\n    return null;\n}\n```\n\n## Queries\nIn RavenDB, a query can only be satisfied by an index. You can create your own indexes, but if no appropriate index exists, \nRavenDB will automatically create one on the fly. Indexes learn from each new query, and are continuously optimized to \nsatisfy all previous queries made to a given collection. In this way RavenDB is built to optimize the speed of reads with minimal \nadministration. (By default, indexes are updated asynchronously so that they don't impact write speed. In most use cases \nthis improves performance, but you can always have write operations wait for the index to update before returning using \n`session.advanced().waitForIndexesAfterSaveChanges();`.)  \n\nQueries are created by chaining methods on `session.query()`, and executed by calling `.toList()`. Before being sent to the server, every\nquery is translated to [RQL (RavenDB Query Language)](https://ravendb.net/docs/article-page/4.2/java/indexes/querying/what-is-rql) - \nour SQL-like language. RQL was designed to expose RavenDB's query pipeline to the user. You can write your queries in RQL\nusing `session.advanced().rawQuery([RQL string])`. Any query can be converted to RQL by calling `.toString()`. Here are \nsome example queries constructed in Java, accompanied by the equivalent RQL:\n\n### 1. Retrieve all documents from a collection\n```java\nIDocumentQuery\u003cDoctor\u003e query = session.query(Doctor.class);\n```\nThis is the simplest possible query, with no filtering, paging, or projection. The parameter `Doctor.class` indicates the\ntype of the entities retrieved, and also that the collection being queried is `Doctors`.\n\nEquivalent RQL:\n```SQL\nfrom Doctors\n```\n\n### 2. Paging and query statistics\nWe have a grid that displays 10 patients per page. To display the third page, we tell\nour query to `.skip()` the first 20 documents and `.take()` the next 10.  \n\n```java\nReference\u003cQueryStatistics\u003e myQueryStats = new Reference\u003c\u003e();\nIDocumentQuery\u003cPatient\u003e query = session.query(Patient.class)\n                                       .skip(20)\n                                       .take(10)\n                                       .statistics(myQueryStats)\n\nCollection\u003cPatient\u003e myPatients = query.toList();\nint totalResults = myQueryStats.value.getTotalResults();\n```\n\nWe also want to know how many pages there are in total so we can render the page selection buttons. Some useful data, called the\n_query statistics_, are automatically sent to the client along with the response to each query. To save them we \ncall `.statistics(myQueryStats)` and then we can access the total number of results with `myQueryStats.value.getTotalResults()`.\n\nEquivalent RQL:\n```SQL\nfrom Patients\nlimit 10 offset 20\n```\n`limit` corresponds to `.take()` and `offset` corresponds to `.skip()`. There is no command in RQL regarding query statistics,\nsince they are always sent regardless.\n\n### 3.Filtering and including related documents  \nRavenDB does not use joins, like SQL databases do. Instead, if one document contains the id of another document, that other\ndocument can be retrieved by the same query .  \nThis query filters the Patients collection to retrieve only patients with the full name \"John Doe\", and includes the doctor documents\nwhose ids are listed in that patient's visits.  \n\n```java\nCollection\u003cPatient\u003e myPatients = session.query(Patient.class)\n                                        .whereEquals(\"firstName\", \"John\")\n                                        .andAlso()\n                                        .whereEquals(\"lastName\", \"Doe\")\n                                        .include(\"visits[].doctorId\")\n                                        .toList();\n\n// Assume that John Doe has an appointment with `doctors/1-A`.\n// `doctors/1-A` can now be loaded from a local cache rather \n// than by making an additional round trip to the server.\nDoctor myDoctor = session.load(\"doctors/1-A\");\n```\n\nEquivalent RQL:\n```SQL\nfrom Patients\nwhere firstName = 'John' and lastName = 'Doe'\ninclude 'visits[].doctorId'\n```\nAlthough the above raw query works as it is written, if you were to take the method chain form of the query and call \n`toString()`, the result will be:\n```SQL\nfrom Patients\nwhere firstName = $p0 and lastName = $p1\ninclude 'visits[].doctorId'\n```\nWhere `$p0` and `$p1` represent parameters which are sent to the server along with the query, but not in the body of the RQL.\n\n### 4. Aggregating and projecting  \n```java\nList\u003cDoctorVisit\u003e results = session.query(Patient.class)\n                                   .groupBy(\"visits[].doctorId\")\n                                   .selectKey(\"visits[].doctorId\", \"doctorId\")\n                                   .selectCount()\n                                   .whereNotEquals(\"doctorId\", null)\n                                   .orderByDescending(\"count\")\n                                   .ofType(DoctorVisit.class)\n                                   .include(\"visits[].doctorId\")\n                                   .toList();\n```\nIn this query from the demo, we want to rank doctors by the number of visits they have scheduled with patients.  \n`groupBy(\"visits[].doctorId\")` performs a map-reduce operation on the `Patients` collection, grouping by the doctorIds \nlisted in the visits array.  \n\nHowever, since we don't want any of the other data in the patient documents, it would be a waste to send it over the network. \nWith `.selectKey(\"visits[].doctorId\", \"doctorId\")` we retrieve only the doctorIds and with `.selectCount()`, we retrieve the \nnumber of visits per doctor.  \n\n`ofType(DoctorVisit.class)` takes our results and casts them to the type `DoctorVisit`.\n\nEquivalent RQL:\n```SQL\nfrom Patients\ngroup by visits[].doctorId\nwhere doctorId != null\norder by count desc\nselect visits[].doctorId as doctorId, count() as count\ninclude 'visits[].doctorId'\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fravendb%2Fsamples-jvm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fravendb%2Fsamples-jvm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fravendb%2Fsamples-jvm/lists"}