Skip to main content

A Solr client library written in Rust

Project description

Solrstice: A Solr 8+ Client for Rust and Python

Solrstice is a solr client library written in rust. With this wrapper you can use it in python.

Both asyncio and blocking clients are provided. All apis have type hints.

Features

  • Config API
  • Collection API
  • Alias API
  • Select Documents
    • Grouping Component Query
    • DefTypes (lucene, dismax, edismax)
    • Facet Counts (Query, Field, Pivot)
    • Json Facet (Query, Stat, Terms, Nested)
  • Indexing Documents
  • Deleting Documents

Installation

pip install solrstice

Basic Usage

Async

import asyncio

from solrstice import SolrBasicAuth, SolrServerContext, SolrSingleServerHost, AsyncSolrCloudClient, UpdateQuery, \
    SelectQuery, DeleteQuery

# A SolrServerContext specifies how the library should interact with Solr
context = SolrServerContext(SolrSingleServerHost('localhost:8983'), SolrBasicAuth('solr', 'SolrRocks'))
client = AsyncSolrCloudClient(context)


async def main() -> None:
    # Create config and collection
    await client.upload_config('example_config', 'path/to/config')
    await client.create_collection('example_collection', 'example_config', shards=1, replication_factor=1)

    # Index a document
    await client.index(UpdateQuery(), 'example_collection', [{'id': 'example_document', 'title': 'Example document'}])

    # Search for the document
    response = await client.select(SelectQuery(fq=['title:Example document']), 'example_collection')
    docs_response = response.get_docs_response()
    assert docs_response is not None
    assert docs_response.get_num_found() == 1
    docs = docs_response.get_docs()

    # Delete the document
    await client.delete(DeleteQuery(ids=['example_document']), 'example_collection')


asyncio.run(main())

Blocking

from solrstice import SolrBasicAuth, BlockingSolrCloudClient, SolrServerContext, SolrSingleServerHost, DeleteQuery, \
    SelectQuery, UpdateQuery

# A SolrServerContext specifies how the library should interact with Solr
context = SolrServerContext(SolrSingleServerHost('localhost:8983'), SolrBasicAuth('solr', 'SolrRocks'))
client = BlockingSolrCloudClient(context)

# Create config and collection
client.upload_config('example_config', 'path/to/config')
client.create_collection('example_collection', 'example_config', shards=1, replication_factor=1)

# Index a document
client.index(UpdateQuery(), 'example_collection', [{'id': 'example_document', 'title': 'Example document'}])

# Search for the document
response = client.select(SelectQuery(fq=['title:Example document']), 'example_collection')
docs_response = response.get_docs_response()
assert docs_response is not None
assert docs_response.get_num_found() == 1
docs = docs_response.get_docs()

# Delete the document
client.delete(DeleteQuery(ids=['example_document']), 'example_collection')

Grouping component

Field grouping

from solrstice import GroupingComponent, SelectQuery, SolrServerContext, AsyncSolrCloudClient
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main() -> None:
  group_builder = GroupingComponent(fields=["age"], limit=10)
  select_builder = SelectQuery(fq=["age:[* TO *]"], grouping=group_builder)
  groups = (await client.select(select_builder, "example_collection")).get_groups()
  age_group = groups["age"]
  docs = age_group.get_field_result()

Query grouping

from solrstice import GroupingComponent, SelectQuery, SolrServerContext, AsyncSolrCloudClient
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main() -> None:
  group_builder = GroupingComponent(queries=["age:[0 TO 59]", "age:[60 TO *]"], limit=10)
  select_builder = SelectQuery(fq=["age:[* TO *]"], grouping=group_builder)
  groups = (await client.select(select_builder, "example_collection")).get_groups()
  age_group = groups["age:[0 TO 59]"]
  group = age_group.get_query_result()
  assert group is not None
  docs = group.get_docs()

Query parsers

Lucene

from solrstice import LuceneQuery, SelectQuery, SolrServerContext, AsyncSolrCloudClient
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main() -> None:
  query_parser = LuceneQuery(df="population")
  select_builder = SelectQuery(q="outdoors", def_type=query_parser)
  response = (await client.select(select_builder, "example_collection")).get_docs_response()
  assert response is not None
  docs = response.get_docs()

Dismax

from solrstice import DismaxQuery, SelectQuery, SolrServerContext, AsyncSolrCloudClient
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main() -> None:
  query_parser = DismaxQuery(qf="interests^20", bq=["interests:cars^20"])
  select_builder = SelectQuery(q="outdoors", def_type=query_parser)
  response = (await client.select(select_builder, "example_collection")).get_docs_response()
  assert response is not None
  docs = response.get_docs()

Edismax

from solrstice import EdismaxQuery, SelectQuery, SolrServerContext, AsyncSolrCloudClient
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main() -> None:
  query_parser = EdismaxQuery(qf="interests^20", bq=["interests:cars^20"])
  select_builder = SelectQuery(q="outdoors", def_type=query_parser)
  response = (await client.select(select_builder, "example_collection")).get_docs_response()
  assert response is not None
  docs = response.get_docs()

FacetSet Component

Pivot facet

from solrstice import FacetSetComponent, PivotFacetComponent, SelectQuery, SolrServerContext, AsyncSolrCloudClient
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main() -> None:
  select_builder = SelectQuery(facet_set=FacetSetComponent(pivots=PivotFacetComponent(["interests,age"])))
  response = await client.select(select_builder, "example_collection")
  facets = response.get_facet_set()
  pivots = facets.get_pivots()
  interests_age = pivots.get("interests,age")

Field facet

from solrstice import FacetSetComponent, FieldFacetComponent, FieldFacetEntry, SelectQuery, SolrServerContext, AsyncSolrCloudClient
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main() -> None:
  facet_set = FacetSetComponent(fields=FieldFacetComponent(fields=[FieldFacetEntry("age")]))
  select_builder = SelectQuery(facet_set=facet_set)
  response = await client.select(select_builder, "example_collection")
  facets = response.get_facet_set()
  fields = facets.get_fields()
  age = fields.get("age")

Query facet

from solrstice import AsyncSolrCloudClient, SolrServerContext, SelectQuery, FacetSetComponent, FacetSetComponent
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main() -> None:
  select_builder = SelectQuery(facet_set=FacetSetComponent(queries=["age:[0 TO 59]"]))
  response = await client.select(select_builder, "example_collection")
  facets = response.get_facet_set()
  queries = facets.get_queries()
  query = queries.get("age:[0 TO 59]")

Json Facet Component

Query

from solrstice import JsonFacetComponent, JsonQueryFacet, SelectQuery, SolrServerContext, AsyncSolrCloudClient
async def main() -> None:
  client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))
  select_builder = SelectQuery(
      json_facet=JsonFacetComponent(
          facets={"below_60": JsonQueryFacet("age:[0 TO 59]")}
      )
  )
  response = await client.select(select_builder, "example_collection")
  facets = response.get_json_facets()
  assert facets is not None
  below_60 = facets.get_nested_facets().get("below_60")
  assert below_60 is not None
  assert below_60.get_count() == 4

Stat

from solrstice import JsonFacetComponent, JsonStatFacet, SelectQuery, SolrServerContext, AsyncSolrCloudClient
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main() -> None:
  select_builder = SelectQuery(
      json_facet=JsonFacetComponent(
          facets={"total_people": JsonStatFacet("sum(count)")}
      )
  )
  response = await client.select(select_builder, "example_collection")
  facets = response.get_json_facets()
  assert facets is not None
  total_people = facets.get_flat_facets()["total_people"]
  assert total_people == 1000

Terms

from solrstice import AsyncSolrCloudClient, SolrServerContext, SelectQuery, JsonFacetComponent, JsonTermsFacet
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main() -> None:
  select_builder = SelectQuery(
      json_facet=JsonFacetComponent(facets={"age": JsonTermsFacet("age")})
  )
  response = await client.select(select_builder, "example_collection")
  facets = response.get_json_facets()
  assert facets is not None
  age_buckets = facets.get_nested_facets()["age"].get_buckets()
  assert len(age_buckets) == 3

Nested

from solrstice import AsyncSolrCloudClient, SolrServerContext, SelectQuery, JsonFacetComponent, JsonQueryFacet, JsonStatFacet
client = AsyncSolrCloudClient(SolrServerContext('localhost:8983'))

async def main() -> None:
  select_builder = SelectQuery(
      json_facet=JsonFacetComponent(
          facets={
              "below_60": JsonQueryFacet(
                  "age:[0 TO 59]",
                  facets={"total_people": JsonStatFacet("sum(count)")},
              )
          }
      )
  )
  response = await client.select(select_builder, "example_collection")
  facets = response.get_json_facets()
  assert facets is not None
  total_people = (
      facets.get_nested_facets()
      ["below_60"]
      .get_flat_facets()
      .get("total_people")
  )
  assert total_people == 750.0

Hosts

Single Server

from solrstice import SolrServerContext, SolrSingleServerHost, SolrBasicAuth, AsyncSolrCloudClient

context = SolrServerContext(SolrSingleServerHost('localhost:8983'), SolrBasicAuth('solr', 'SolrRocks'))
client = AsyncSolrCloudClient(context)

Multiple servers

from solrstice import SolrServerContext, SolrMultipleServerHost, SolrBasicAuth, AsyncSolrCloudClient

# The client will randomly select a server to send requests to. It will wait 5 seconds for a response, before trying another server.
context = SolrServerContext(
    SolrMultipleServerHost(["localhost:8983", "localhost:8984"], 5),
    SolrBasicAuth('solr', 'SolrRocks'),
)
client = AsyncSolrCloudClient(context)

Zookeeper

from solrstice import SolrServerContext, ZookeeperEnsembleHostConnector, SolrBasicAuth, AsyncSolrCloudClient

async def main() -> None:
  context = SolrServerContext(
      await ZookeeperEnsembleHostConnector(["localhost:2181"], 30).connect(),
      SolrBasicAuth('solr', 'SolrRocks'),
  )
  client = AsyncSolrCloudClient(context)

Notes

  • Multiprocessing does not work, and will block forever. Normal multithreading works fine.

  • Pyo3, the Rust library for creating bindings does not allow overriding the __init__ method on objects from Rust. __new__ has to be overridden instead.

    For example, if you want to create a simpler way to create a client

    from typing import Optional
    from solrstice import SolrServerContext, SolrSingleServerHost, SolrBasicAuth, AsyncSolrCloudClient, SolrAuth
    class SolrClient(AsyncSolrCloudClient):
        def __new__(cls, host: str, auth: Optional[SolrAuth] = None):
            context = SolrServerContext(SolrSingleServerHost(host), auth)
            return super().__new__(cls, context=context)
    client = SolrClient("localhost:8983", SolrBasicAuth("username", "password"))
    

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

solrstice-0.8.0.tar.gz (101.6 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

solrstice-0.8.0-cp38-abi3-win_amd64.whl (3.2 MB view details)

Uploaded CPython 3.8+Windows x86-64

solrstice-0.8.0-cp38-abi3-musllinux_1_2_x86_64.whl (4.1 MB view details)

Uploaded CPython 3.8+musllinux: musl 1.2+ x86-64

solrstice-0.8.0-cp38-abi3-musllinux_1_2_armv7l.whl (3.8 MB view details)

Uploaded CPython 3.8+musllinux: musl 1.2+ ARMv7l

solrstice-0.8.0-cp38-abi3-musllinux_1_2_aarch64.whl (3.9 MB view details)

Uploaded CPython 3.8+musllinux: musl 1.2+ ARM64

solrstice-0.8.0-cp38-abi3-manylinux_2_28_x86_64.whl (3.9 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.28+ x86-64

solrstice-0.8.0-cp38-abi3-manylinux_2_28_s390x.whl (4.2 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.28+ s390x

solrstice-0.8.0-cp38-abi3-manylinux_2_28_ppc64le.whl (3.9 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.28+ ppc64le

solrstice-0.8.0-cp38-abi3-manylinux_2_28_armv7l.whl (3.6 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.28+ ARMv7l

solrstice-0.8.0-cp38-abi3-manylinux_2_28_aarch64.whl (3.8 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.28+ ARM64

solrstice-0.8.0-cp38-abi3-macosx_11_0_arm64.whl (3.4 MB view details)

Uploaded CPython 3.8+macOS 11.0+ ARM64

solrstice-0.8.0-cp38-abi3-macosx_10_12_x86_64.whl (3.6 MB view details)

Uploaded CPython 3.8+macOS 10.12+ x86-64

File details

Details for the file solrstice-0.8.0.tar.gz.

File metadata

  • Download URL: solrstice-0.8.0.tar.gz
  • Upload date:
  • Size: 101.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.8.2

File hashes

Hashes for solrstice-0.8.0.tar.gz
Algorithm Hash digest
SHA256 92ddd1674e2755e78c7825d16a7a43316f75156aecc66a6137a8782c1e7497d0
MD5 b92ee6e5043c009f788259ebf00a72e8
BLAKE2b-256 66eb9124cc02d39d54ce99f4931fab38ba4f5bd8fc984766b14e5cab1267b52b

See more details on using hashes here.

File details

Details for the file solrstice-0.8.0-cp38-abi3-win_amd64.whl.

File metadata

  • Download URL: solrstice-0.8.0-cp38-abi3-win_amd64.whl
  • Upload date:
  • Size: 3.2 MB
  • Tags: CPython 3.8+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.8.2

File hashes

Hashes for solrstice-0.8.0-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 d774c27e8cfae48360c9ac9d7c579f6fd37854c07cf2ceac7b7589f157f5e1cd
MD5 6f30ca1e7e026e76228e0424627f9b7e
BLAKE2b-256 f0c03df1e67368a0c3a0d94f5c6bfdbd46a9708547d731d9281120c4e8136a18

See more details on using hashes here.

File details

Details for the file solrstice-0.8.0-cp38-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for solrstice-0.8.0-cp38-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 9cc9baeb58b0994535c196fdb07947b2c63060c5891169f22d590dcc3d9c1438
MD5 160dfe7b0ede13ce09615dfb13496e34
BLAKE2b-256 f4b4e2e5515834583c2047524b4f298b6a5da4a904bd7ce154f30b4d278ef58f

See more details on using hashes here.

File details

Details for the file solrstice-0.8.0-cp38-abi3-musllinux_1_2_armv7l.whl.

File metadata

File hashes

Hashes for solrstice-0.8.0-cp38-abi3-musllinux_1_2_armv7l.whl
Algorithm Hash digest
SHA256 217213e3604a0a988772a85dd6661fe467b9497ccb2c022f1fbe4d79331b2ee0
MD5 8ff97049455d5dfa5fe181203ab9e927
BLAKE2b-256 e6db6ecfac7e788b9d6d15a29e6eaa655c49e6e3276c7b08997936a32f69bc55

See more details on using hashes here.

File details

Details for the file solrstice-0.8.0-cp38-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for solrstice-0.8.0-cp38-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 831940b2d929a8b4f0416151415ea7687b9d5bd79a1487349c36f7c1fdf59112
MD5 ba4d3399e630d3d182e22d8911812129
BLAKE2b-256 361156f8ba7dafb300714d2d0a241b4e14e0748abe352024cbdc0d16be1af4a9

See more details on using hashes here.

File details

Details for the file solrstice-0.8.0-cp38-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for solrstice-0.8.0-cp38-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a17d0158f1590cb02aee5b1beb7d0da97ec8954064a5f9278f9ad754c7c3d340
MD5 3dc7b92a2e7cf20de6da757c46860ac2
BLAKE2b-256 04814608ab251c6a3e94d69bef2747794cc2a6f4b3fcb7a83d56b05c0f0f23ef

See more details on using hashes here.

File details

Details for the file solrstice-0.8.0-cp38-abi3-manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for solrstice-0.8.0-cp38-abi3-manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 7eace2294b48d7acff39fca76248e23f0fc531b30aaaf62404606b0ef6c7a2b8
MD5 f090a113b9f7db5868e8edd6c4b2bff0
BLAKE2b-256 ddba68a011a2ac7c15986c138d8496337da99f54a7a5aefdd34d5c2dab2931d7

See more details on using hashes here.

File details

Details for the file solrstice-0.8.0-cp38-abi3-manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for solrstice-0.8.0-cp38-abi3-manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 6e84bd3dc223da04114408dd40d07b8bab2bc88d400eb45d222d93ea7ec1c483
MD5 acd03ca561bb5136c679803b184a0b9f
BLAKE2b-256 5f30548ef1515caddb5b86654efaf450c5a4925ed8eb7bbedcb151ea3dcf672b

See more details on using hashes here.

File details

Details for the file solrstice-0.8.0-cp38-abi3-manylinux_2_28_armv7l.whl.

File metadata

File hashes

Hashes for solrstice-0.8.0-cp38-abi3-manylinux_2_28_armv7l.whl
Algorithm Hash digest
SHA256 e61a6a23ee03017d268b3a8fa16acdef996a8ee99f9fd47b60c93460208a35ba
MD5 b2dcd93db48e279cd1bfc5ed544ef3c0
BLAKE2b-256 f8b14927e89ef8e0dbb88be1dd722701fc4deffc660250d7c009af3788d50a2e

See more details on using hashes here.

File details

Details for the file solrstice-0.8.0-cp38-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for solrstice-0.8.0-cp38-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 c86a8722f239aa575843a4acd60a0aa7219358e8e3e643e009fe2e646d705c98
MD5 3a55851e160691d14bec21254ead7317
BLAKE2b-256 14e5744c8e67fe234700f4fd28441a7f5aa1f90b58eefe248b8ce2e11fc83eaf

See more details on using hashes here.

File details

Details for the file solrstice-0.8.0-cp38-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for solrstice-0.8.0-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 01122234253ae08d6b8daf78e5029008222c526cfcd7d4331c323c148eeb9bc6
MD5 58961474ab875b48072f17ab1c18ffbd
BLAKE2b-256 a1e9ce69f16d51ecdb0da5ee55ea417b203fdefbaa68083a5f8b5c8dcbcceb6e

See more details on using hashes here.

File details

Details for the file solrstice-0.8.0-cp38-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for solrstice-0.8.0-cp38-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 f91c733f22641820f96e21a96c8085074249e05bd7e01038131c2144998fffe1
MD5 c13a58708a2b4d613627560f1a822f19
BLAKE2b-256 5f1db03bcb3a7b1ee73a4aa030c1541b3911eb594ef0fba98f0ffddf4fd68cfa

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page