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
    • Stats Component
    • 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]")

Stats Component

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

async def main() -> None:
  select_builder = SelectQuery(stats=StatsComponent(fields=["age"]))
  response = await client.select(select_builder, "example_collection")
  stats = response.get_stats()
  assert stats is not None
  age_stats = stats.get_fields()["age"]
  age_count = age_stats.get_count()

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(q="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(
                  q="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.14.0.tar.gz (110.7 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.14.0-cp39-abi3-win_amd64.whl (3.3 MB view details)

Uploaded CPython 3.9+Windows x86-64

solrstice-0.14.0-cp39-abi3-musllinux_1_2_x86_64.whl (4.3 MB view details)

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

solrstice-0.14.0-cp39-abi3-musllinux_1_2_armv7l.whl (4.0 MB view details)

Uploaded CPython 3.9+musllinux: musl 1.2+ ARMv7l

solrstice-0.14.0-cp39-abi3-musllinux_1_2_aarch64.whl (4.2 MB view details)

Uploaded CPython 3.9+musllinux: musl 1.2+ ARM64

solrstice-0.14.0-cp39-abi3-manylinux_2_28_x86_64.whl (4.0 MB view details)

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

solrstice-0.14.0-cp39-abi3-manylinux_2_28_s390x.whl (4.0 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.28+ s390x

solrstice-0.14.0-cp39-abi3-manylinux_2_28_ppc64le.whl (4.6 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.28+ ppc64le

solrstice-0.14.0-cp39-abi3-manylinux_2_28_armv7l.whl (3.8 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.28+ ARMv7l

solrstice-0.14.0-cp39-abi3-manylinux_2_28_aarch64.whl (4.0 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.28+ ARM64

solrstice-0.14.0-cp39-abi3-macosx_11_0_arm64.whl (3.6 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

File details

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

File metadata

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

File hashes

Hashes for solrstice-0.14.0.tar.gz
Algorithm Hash digest
SHA256 c92db033ef03228aeaade20879479fcad6c4596d445cd092a7888ad3c16d4014
MD5 9ff4c762c4febe3b88a5ccdda107d2a0
BLAKE2b-256 67db70e83fe3ff99e5e797b6c1c8c2d3d933025d5f55d4220d0d3d8cf1927de3

See more details on using hashes here.

File details

Details for the file solrstice-0.14.0-cp39-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for solrstice-0.14.0-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 6f10fa1ba13e2a9633d89dde3b7e7c6ddf4a867f779378bb4f74fe61489e3b52
MD5 dfb5406e4cd774f0c5dad02ce81a0ce7
BLAKE2b-256 5de0d3c63550ff2f3dd81400b548c530fe9bc23c149399fef9d4bc4d0a5acb9b

See more details on using hashes here.

File details

Details for the file solrstice-0.14.0-cp39-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for solrstice-0.14.0-cp39-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 ae726e54318218a78679fd7664afc897fe9198ccbbd0a6dd9a2599ecedc0d289
MD5 00725a9fe2732bef2855c48ef93c9ac8
BLAKE2b-256 a4deb5a6ff82dc3aa02dfe637503ec5f87dbfbdbf8deb9ed7decbdbf92942c4c

See more details on using hashes here.

File details

Details for the file solrstice-0.14.0-cp39-abi3-musllinux_1_2_armv7l.whl.

File metadata

File hashes

Hashes for solrstice-0.14.0-cp39-abi3-musllinux_1_2_armv7l.whl
Algorithm Hash digest
SHA256 79e4a2828a5a532db1349c066970f817d641490019f6e9df4376b6463f8f3088
MD5 fbc8bebc9ac2f27169a6ef69b91258d2
BLAKE2b-256 5682dbfa57b578f08d62e0a0fafb2f4f3f581b481ba6b791ef08f4565d742ebd

See more details on using hashes here.

File details

Details for the file solrstice-0.14.0-cp39-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for solrstice-0.14.0-cp39-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 9ba16f308b32d740fe3ec976497f137ccf6b47eb2c3d9758d57ce9c5d37791b9
MD5 9a450da10f81b69ceb9186f7eda21367
BLAKE2b-256 631b614c0954428ec99117499b45c9288d2bc11c4bef432caa4398a398553129

See more details on using hashes here.

File details

Details for the file solrstice-0.14.0-cp39-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for solrstice-0.14.0-cp39-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 7597662ef2defdbf7971c453bb341ab1fde53df6a04d8e29eecdf9175d3b2659
MD5 a092db379e55d8319d70a670c32c5553
BLAKE2b-256 666f98c414c61abfabd8029e5e092c9afa528c272e72d626d532936ec023e784

See more details on using hashes here.

File details

Details for the file solrstice-0.14.0-cp39-abi3-manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for solrstice-0.14.0-cp39-abi3-manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 dc8f7cd8e38bcce665c8db7431436cfa482eca96ae27f299fd77b98d833c3393
MD5 d32643ebb2c42694477e1c29aacf40f6
BLAKE2b-256 63684c2e66f486f6af030b0fdc1f00034dc615f0061298326ac83d4434ce6779

See more details on using hashes here.

File details

Details for the file solrstice-0.14.0-cp39-abi3-manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for solrstice-0.14.0-cp39-abi3-manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 725865aca64d7ace4f43481db605033954873678fbfa086cc75cc507fb457236
MD5 6248e6add0baf91a07f90459eb933e27
BLAKE2b-256 54acc1a7e6842dfa74748b04e05461c2e70a082e87872cd4ea5678e9f0ea80c1

See more details on using hashes here.

File details

Details for the file solrstice-0.14.0-cp39-abi3-manylinux_2_28_armv7l.whl.

File metadata

File hashes

Hashes for solrstice-0.14.0-cp39-abi3-manylinux_2_28_armv7l.whl
Algorithm Hash digest
SHA256 09f3dfe56c2737b51d233d908ee9bcbd0b1740b9bd4f131a703f83de300bd03e
MD5 b551aab055120385704b9d1517c42397
BLAKE2b-256 64adfc5b440568add3d6d09944bfab6c5ed5363531e971d4a8df9c303e3a5d43

See more details on using hashes here.

File details

Details for the file solrstice-0.14.0-cp39-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for solrstice-0.14.0-cp39-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 7c071524e7da15fba2e5cfcebc6a8d498d695c985146f49adc2ce5253337dfa8
MD5 d83793f0296975b8e8eb8f82d582ffe0
BLAKE2b-256 c5f2e7bacf0d4cb65f69357acd33b398592d713d3bb003ba52622df386555f85

See more details on using hashes here.

File details

Details for the file solrstice-0.14.0-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for solrstice-0.14.0-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ba179007c989f2d21c10ebb45fc1ac619b8ce9996f564fda4040775577c94464
MD5 2c7ceef92e0d06f6258e77cbf501b6a2
BLAKE2b-256 b85c606ba0793dd3f591c7f36821e1e9507c63508e3d2cbfd7554a93780ebab1

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