11import json
2- from requests import Session
2+ from requests import Session , Response
33
44"""
55Defines a RowManager class to simplify usage of the "/v1/rows" & "/v1/rows/graphql" REST
@@ -11,10 +11,11 @@ class RowManager:
1111 """
1212 Provides a method to simplify sending a GraphQL request to the GraphQL rows endpoint.
1313 """
14+
1415 def __init__ (self , session : Session ):
1516 self ._session = session
16-
17- def graphql (self , graphql_query , return_response = False , * args , ** kwargs ):
17+
18+ def graphql (self , graphql_query : str , return_response : bool = False , * args , ** kwargs ):
1819 """
1920 Send a GraphQL query to MarkLogic via a POST to the endpoint defined at
2021 https://docs.marklogic.com/REST/POST/v1/rows/graphql
@@ -40,4 +41,92 @@ def graphql(self, graphql_query, return_response=False, *args, **kwargs):
4041 response .json ()
4142 if response .status_code == 200 and not return_response
4243 else response
43- )
44+ )
45+
46+ __accept_switch = {
47+ "json" : "application/json" ,
48+ "xml" : "application/xml" ,
49+ "csv" : "text/csv" ,
50+ "json-seq" : "application/json-seq" ,
51+ "mixed" : "application/xml, multipart/mixed"
52+ }
53+
54+ __query_format_switch = {
55+ "json" : lambda response : response .json (),
56+ "xml" : lambda response : response .text ,
57+ "csv" : lambda response : response .text ,
58+ "json-seq" : lambda response : response .text ,
59+ "mixed" : lambda response : response
60+ }
61+
62+ def query (self , dsl : str = None , plan : dict = None , sql : str = None , sparql : str = None , format : str = "json" , return_response : bool = False , * args , ** kwargs ):
63+ """
64+ Send a query to MarkLogic via a POST to the endpoint defined at
65+ https://docs.marklogic.com/REST/POST/v1/rows
66+ Just like that endpoint, this function can be used for four different types of
67+ queries: Optic DSL, Serialized Optic, SQL, and SPARQL. The type of query
68+ processed by the function is dependent upon the parameter used in the call to
69+ the function.
70+ For more information about Optic and using the Optic DSL, SQL, and SPARQL,
71+ see https://docs.marklogic.com/guide/app-dev/OpticAPI
72+ If multiple query parameters are passed into the call, the function uses the
73+ query parameter that is first in the list: dsl, plan, sql, sparql.
74+
75+ :param dsl: an Optic DSL query
76+ :param plan: a serialized Optic query
77+ :param sql: an SQL query
78+ :param sparql: a SPARQL query
79+ :param return_response: boolean specifying if the entire original response
80+ object should be returned (True) or if only the data should be returned (False)
81+ upon a success (2xx) response. Note that if the status code of the response is
82+ not 2xx, then the entire response is always returned.
83+ """
84+ request_info = self .__get_request_info (dsl , plan , sql , sparql )
85+ headers = kwargs .pop ("headers" , {})
86+ headers ["Content-Type" ] = request_info ["content-type" ]
87+ headers ["Accept" ] = RowManager .__accept_switch .get (format )
88+ response = self ._session .post (
89+ "v1/rows" ,
90+ headers = headers ,
91+ data = request_info ["data" ],
92+ ** kwargs
93+ )
94+ return (
95+ RowManager .__query_format_switch .get (format )(response )
96+ if response .status_code == 200 and not return_response
97+ else response
98+ )
99+
100+ def __get_request_info (self , dsl : str , plan : dict , sql : str , sparql : str ):
101+ """
102+ Examine the parameters passed into the query function to determine what value
103+ should be passed to the endpoint and what the content-type header should be.
104+
105+ :param dsl: an Optic DSL query
106+ :param plan: a serialized Optic query
107+ :param sql: an SQL query
108+ :param sparql: a SPARQL query
109+ dict object returned contains the two values required to make the POST request.
110+ """
111+ if dsl is not None :
112+ return {
113+ "content-type" : "application/vnd.marklogic.querydsl+javascript" ,
114+ "data" : dsl
115+ }
116+ if plan is not None :
117+ return {
118+ "content-type" : "application/json" ,
119+ "data" : plan
120+ }
121+ if sql is not None :
122+ return {
123+ "content-type" : "application/sql" ,
124+ "data" : sql
125+ }
126+ if sparql is not None :
127+ return {
128+ "content-type" : "application/sparql-query" ,
129+ "data" : sparql
130+ }
131+ else :
132+ raise ValueError ("No query found; must specify one of: dsl, plan, sql, or sparql" )
0 commit comments