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.6.1.tar.gz (101.1 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.6.1-cp38-abi3-win_amd64.whl (3.2 MB view details)

Uploaded CPython 3.8+Windows x86-64

solrstice-0.6.1-cp38-abi3-win32.whl (2.7 MB view details)

Uploaded CPython 3.8+Windows x86

solrstice-0.6.1-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.6.1-cp38-abi3-manylinux_2_28_s390x.whl (4.2 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.28+ s390x

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

Uploaded CPython 3.8+manylinux: glibc 2.28+ ppc64le

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

Uploaded CPython 3.8+manylinux: glibc 2.28+ ARMv7l

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

Uploaded CPython 3.8+manylinux: glibc 2.28+ ARM64

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

Uploaded CPython 3.8+macOS 11.0+ ARM64

solrstice-0.6.1-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.6.1.tar.gz.

File metadata

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

File hashes

Hashes for solrstice-0.6.1.tar.gz
Algorithm Hash digest
SHA256 8a1958a2ee7dfa8e140561d929dfbd967ae362fecd6bead5faf677810ef02893
MD5 af0edb7d61add066c15166da4ee38749
BLAKE2b-256 ebe023809c86b40f79d671c73533865e05ab63793743cceaf6078293bafc48d1

See more details on using hashes here.

File details

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

File metadata

  • Download URL: solrstice-0.6.1-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.1

File hashes

Hashes for solrstice-0.6.1-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 261f14d0ca7058b891485a6b96c953c8a2c6a07cddf5733cec4198d436960c21
MD5 c3e631bc79658f73b29c56b00a7c4420
BLAKE2b-256 f1ccf7f7aa917486193b1dc7487cbe4b21ca46b7a546b065c90988efa2f1cee2

See more details on using hashes here.

File details

Details for the file solrstice-0.6.1-cp38-abi3-win32.whl.

File metadata

  • Download URL: solrstice-0.6.1-cp38-abi3-win32.whl
  • Upload date:
  • Size: 2.7 MB
  • Tags: CPython 3.8+, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.8.1

File hashes

Hashes for solrstice-0.6.1-cp38-abi3-win32.whl
Algorithm Hash digest
SHA256 941d580932056d9ac0dd4837789dc5588c419a217dfa2a3ad59920ede788f674
MD5 cb36dea402ffa8c1ecc6e9b2a26fd5b1
BLAKE2b-256 f52cf43a73318968ab8e8f6886ef3676d2be53321382913726628af5a365966e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for solrstice-0.6.1-cp38-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a0cc87e0e547500b8fb5d50bcdd61711a5ea1ec84b066599e54be716f8d8d702
MD5 c0d4a9b52e8e0ed37b18bf3cf38f15ec
BLAKE2b-256 91c04c0eb421b7bc8220c234dd899fd1585880680c77724ded08a25d5108b456

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for solrstice-0.6.1-cp38-abi3-manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 797949ddf2697c762d74527ff98f8a612985adff7260b68d9355d67b4f176e64
MD5 3af57709a9cef7ec09c3fdbaf2bd5195
BLAKE2b-256 6edd7b520639f6db20c4045a7fdeb7038d61849048fdb5a20a71f28ffab10198

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for solrstice-0.6.1-cp38-abi3-manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 71ee573076d86442c63a7d2048ea7d140c518514ed4d547a1f90c3121d6434b3
MD5 134d0ec11424493176432c8af436a1a9
BLAKE2b-256 592457dddb4fbf6434f7df71b32af837cb78f2f99d16fd835e96fdc966d06646

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for solrstice-0.6.1-cp38-abi3-manylinux_2_28_armv7l.whl
Algorithm Hash digest
SHA256 71076a8d59d2e31969c8f757f8977c520a672fc3f484ca2f339cb5886c1c1b01
MD5 2a893802a2666a214984cbf0292bda09
BLAKE2b-256 bbf98cfd1fb0d8cd55107c55de1782b1fed6248fc5622e738d8f58b4cf4529be

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for solrstice-0.6.1-cp38-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 e06ab8e4d0d76d8bdffd5a0014274b2afd34648348d17f3952bbf208e7a59dbd
MD5 0a64d84452f6ac9b562fc48677945b54
BLAKE2b-256 ebcc30cba31494fbf993330d72a4ebf54b9551877adc8226ed54966b4cc47157

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for solrstice-0.6.1-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2eae0acc807a415f6f47a94ad4103d256b9579eea7e60d593f153379fa36c547
MD5 48cae075eb0d830831cf0dc107ca134d
BLAKE2b-256 774e972e74e4523479534fa64a033009341229cbaabb5e14a670c9d87cf7477f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for solrstice-0.6.1-cp38-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 4fc3783c9cdfd3b47c380c98dd7b4b4495184b904d2f9b29e836b61a1b339b8b
MD5 adaafbbd6d8de5f884f7f45de7e1f041
BLAKE2b-256 73550fb9cb67c898f41679ec12052009198d92c8b40bc0a656c71c8d5ad5a35c

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