Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/example-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ Then perform the following steps to create a new user:
1. Click on "Users" in the "Security" box.
2. Click on "Create".
3. In the form, enter "python-user" for "User Name" and "pyth0n" as the password.
4. Scroll down until you see the "Roles" section. Click on the "rest-reader" and "rest-writer" checkboxes.
4. Scroll down until you see the "Roles" section. Click on the "rest-reader", "rest-writer", and "security" checkboxes.
5. Scroll to the top or bottom and click on "OK" to create the user.

(The `security` role is only needed to allow for the user to load documents into the out-of-the-box Schemas database
in MarkLogic; in a production application, an admin or admin-like user would typically be used for this use case.)

You can verify that you correctly created the user by accessing the REST API for the out-of-the-box REST API
server in MarkLogic that listens on port 8000. Go to <http://localhost:8000/v1/search> (changing "localhost" to
the correct name of your MarkLogic host if you are not running it locally) in a web browser and enter the
Expand Down
2 changes: 1 addition & 1 deletion docs/managing-documents/managing-documents.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ has_children: true
permalink: /documents
---

The [/v1/documents endpoint](https://docs.marklogic.com/REST/client/management) in the MarkLogic REST API supports
The [MarkLogic REST documents service](https://docs.marklogic.com/REST/client/management) supports
operations that involve writing or reading a single document. It also supports operations that involve multiple
documents, though those require use of a potentially complex multipart HTTP request or response. The MarkLogic Python
client simplifies those operations by hiding the details of multipart requests and responses.
152 changes: 152 additions & 0 deletions docs/rows.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
---
layout: default
title: Querying for rows
nav_order: 4
---


The [MarkLogic REST rows service](https://docs.marklogic.com/REST/client/row-management) supports
operations for querying for rows via a variety of languages. The MarkLogic Python client simplifies submitting queries
for rows and converting the response into a useful data structure.

## Setup

The examples below require documents to be loaded along with a
[TDE view](https://docs.marklogic.com/guide/app-dev/TDE) that projects rows from the documents. You must also have
performed the instructions in the [setup guide](example-setup.md).

Run the following in a Python shell to load 4 documents, each capturing details about a musician:

```
from marklogic import Client
from marklogic.documents import Document, DefaultMetadata
client = Client('http://localhost:8000', digest=('python-user', 'pyth0n'))

client.documents.write([
DefaultMetadata(permissions={"rest-reader": ["read", "update"]}, collections=["musician"]),
Document("/musician1.json", {"lastName": "Armstrong", "firstName": "Louis", "dob": "1901-08-04"}),
Document("/musician2.json", {"lastName": "Byron", "firstName": "Don", "dob": "1958-11-08"}),
Document("/musician3.json", {"lastName": "Coltrane", "firstName": "John", "dob": "1926-09-23"}),
Document("/musician4.json", {"lastName": "Davis", "firstName": "Miles", "dob": "1926-05-26"})
])
```

Now load a TDE view via the following:

```
tde_view = {
"template": {
"context": "/",
"collections": ["musician"],
"rows": [{
"schemaName": "example",
"viewName": "musician",
"columns": [
{"name": "lastName", "scalarType": "string", "val": "lastName"},
{"name": "firstName", "scalarType": "string", "val": "firstName"},
{"name": "dob", "scalarType": "date", "val": "dob"}
]
}]
}
}

client.documents.write(
Document(
"/tde/musicians.json", tde_view,
permissions={"rest-reader": ["read", "update"]},
collections=["http://marklogic.com/xdmp/tde"]
),
params={"database": "Schemas"}
)
```


## Optic queries

The [MarkLogic Optic API](https://docs.marklogic.com/guide/app-dev/OpticAPI) allows for rows to be queried from
documents via a SQL-like syntax. The [MarkLogic REST API rows service](https://docs.marklogic.com/REST/POST/v1/rows)
accepts Optic queries either as an [Optic Query DSL statement](https://docs.marklogic.com/guide/app-dev/OpticAPI#id_46710)
or as [a serialized plan](https://docs.marklogic.com/guide/app-dev/OpticAPI#id_11208).

Since using an Optic DSL query is often the easiest approach, a DSL query can be submitted as the first argument without
any name:

```
client.rows.query("op.fromView('example', 'musician')")
```

The above will return a JSON object that captures each of the matching rows along with definitions for each column. See
the section below on choosing an output format for controlling how data is returned.


You can use a named argument as well:

```
client.rows.query(dsl="op.fromView('example', 'musician')")
```

For some use cases, it may be helpful to capture an Optic query in its serialized form. Such a query can then be
submitted via the `plan` argument:

```
plan = '{"$optic":{"ns":"op", "fn":"operators", "args":[{"ns":"op", "fn":"from-view", "args":["example", "musician"]}]}}'
client.rows.query(plan=plan)
```

Optic supports many different types of queries and operations; please
[see the documentation]((https://docs.marklogic.com/guide/app-dev/OpticAPI#id_35559)) for further information on
much more powerful and flexible queries than shown in these examples, which are intended solely for demonstration of
how to submit an Optic query.


## SQL queries

MarkLogic supports [SQL queries against views](https://docs.marklogic.com/guide/sql). SQL queries can be submitted
via the `sql` argument:

```
client.rows.query(sql="select * from example.musician order by lastName")
```

This will return a JSON object that captures each of the matching rows along with definitions
for each column. See the section below on choosing an output format for controlling how data is returned.

## SPARQL queries

MarkLogic supports the [SPARQL query language](https://www.w3.org/TR/sparql11-query/), allowing for
[SPARQL queries to be run against views](https://docs.marklogic.com/guide/semantics/semantic-searches#id_94155),
similar to Optic and SQL. SPARQL queries can be submitted via the `sparql` argument:

```
sparql = "PREFIX musician: <http://marklogic.com/column/example/musician/> SELECT * WHERE {?s musician:lastName ?lastName} ORDER BY ?lastName"
client.rows.query(sparql=sparql)
```

This will return a JSON object that captures each of the matching rows along with definitions
for each column. See the section below on choosing an output format for controlling how data is returned.

## GraphQL queries

MarkLogic supports [GraphQL queries](https://docs.marklogic.com/REST/POST/v1/rows/graphql) to be run against views.
A GraphQL query can be submitted via the `graphql` argument:

```
client.rows.query(graphql="query myQuery { example_musician { lastName firstName dob } }")
```

This will return a JSON object containing the matching rows. MarkLogic will only return a JSON object for GraphQL
queries; the `format` argument described below will not have any impact when submitting a GraphQL query.

## Choosing an output format

The [MarkLogic REST endpoint for querying rows](https://docs.marklogic.com/REST/POST/v1/rows) supports several options
for how data is returned via the `format` parameter. The `client.rows.query` function allows for an output format to be
selected via a `format` argument. The following table defined the possible values:

| `format` value | Output format |
| --- | --- |
| `json` | JSON object with keys of 'columns' and 'rows'. |
| `xml` | XML document defining the columns and rows. |
| `csv` | CSV text with the first row defining the columns. |
| `json-seq` | A [line-delimited JSON sequence](https://datatracker.ietf.org/doc/html/rfc7464) with the first row defining the columns. |
| `mixed` | TODO Seems like we should remove this as it does the same thing as "return_response". |
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BillFarber See my note here - thoughts on removing this? I doubt it would ever be used, and return_response=True would be the more consistent way to just get the original multipart/mixed response back.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If 'mixed' just has the same affect as "return_response=true", then I would remove it.
However, would it work and be useful to use Client.process_multipart_mixed_response(response) to pre-process requests with the 'mixed' format?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that I know of yet, and in fact, one reason I'd like to move the eval stuff out of client.py is so that the process_multipart... method isn't yet public. While it may be useful in the future as a public method, we don't know that yet, and I lean towards making things non-public when in doubt (as opposed to what I did with e.g. ml-app-deployer).

6 changes: 3 additions & 3 deletions docs/transactions.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
layout: default
title: Managing transactions
nav_order: 4
nav_order: 5
---

The [/v1/transactions endpoint](https://docs.marklogic.com/REST/client/transaction-management)
in the MarkLogic REST API supports managing a transaction that can be referenced in
The [MarkLogic REST transactions service](https://docs.marklogic.com/REST/client/transaction-management)
supports managing a transaction that can be referenced in
multiple separate calls to other REST API endpoints, with all calls being committed or
rolled back together. The MarkLogic Python client simplifies usage of these endpoints
via a `Transaction` class that is also a
Expand Down
7 changes: 7 additions & 0 deletions shell/docs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Startup script when wanting to hit port 8000 as the user that's setup in the
# documentation.

from marklogic import Client
from marklogic.documents import Document, DefaultMetadata

client = Client("http://localhost:8000", digest=("python-user", "pyth0n"))
4 changes: 4 additions & 0 deletions shell/test_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Startup script when wanting to hit the test-app server on port 8030 in a Python shell.
from marklogic import Client

client = Client("http://localhost:8030", digest=("python-test-user", "password"))
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"user-name": "python-user",
"password": "pyth0n",
"description": "Used by the documentation, not by tests",
"role": [
"rest-reader",
"rest-writer",
"security"
]
}