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
7 changes: 4 additions & 3 deletions sdk/search/azure-search-documents/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@

### Features Added

### Breaking Changes

### Bugs Fixed
- Added properties to `SearchClient.search`: `session_id`, `scoring_statistics`.
- Added properties to `SearchIndexerDataSourceConnection`: `identity`, `encryption_key`.
- Added `select` property to the following `SearchIndexClient` operations: `get_synonym_maps`, `list_indexes`.
- Added `select` property to the following `SearchIndexersClient` operations: `get_data_source_connections`, `get_indexers`, `get_skillsets`.

### Other Changes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,18 @@ def search(self, search_text, **kwargs): # pylint:disable=too-many-locals
$skip to implement client-side paging of search results. If results are truncated due to
server-side paging, the response will include a continuation token that can be used to issue
another Search request for the next page of results.
:keyword scoring_statistics: A value that specifies whether we want to calculate scoring
statistics (such as document frequency) globally for more consistent scoring, or locally, for
lower latency. The default is 'local'. Use 'global' to aggregate scoring statistics globally
before scoring. Using global scoring statistics can increase latency of search queries.
Possible values include: "local", "global".
:paramtype scoring_statistics: str or ~azure.search.documents.models.ScoringStatistics
:keyword str session_id: A value to be used to create a sticky session, which can help getting more
consistent results. As long as the same sessionId is used, a best-effort attempt will be made
to target the same replica set. Be wary that reusing the same sessionID values repeatedly can
interfere with the load balancing of the requests across replicas and adversely affect the
performance of the search service. The value used as sessionId cannot start with a '_'
character.
:rtype: SearchItemPaged[dict]

.. admonition:: Example:
Expand Down Expand Up @@ -274,6 +286,8 @@ def search(self, search_text, **kwargs): # pylint:disable=too-many-locals
select = kwargs.pop("select", None)
skip = kwargs.pop("skip", None)
top = kwargs.pop("top", None)
session_id = kwargs.pop("session_id", None)
scoring_statistics = kwargs.pop("scoring_statistics", None)

query_answer = kwargs.pop("query_answer", None)
query_answer_count = kwargs.pop("query_answer_count", None)
Expand Down Expand Up @@ -312,6 +326,8 @@ def search(self, search_text, **kwargs): # pylint:disable=too-many-locals
select=select if isinstance(select, six.string_types) else None,
skip=skip,
top=top,
session_id=session_id,
Copy link
Member

Choose a reason for hiding this comment

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

Seems like we only need to pass in **kwargs?

Copy link
Member Author

Choose a reason for hiding this comment

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

Essentially, no we can't do that. All of the kwargs get popped in the lines above this section and then plugged in directly to the SearchQuery constructor. I tried to remove that, but then the kwargs get passed along to SearchItemPaged and request blows up due to unexpected keyword arguments, which doesn't seem to be an easy fix. So there's really no value add in deviating from the existing pattern here.

Copy link
Member

Choose a reason for hiding this comment

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

Not 100% sure if I understand correctly, what we need is to pop unwanted parameters before

return SearchItemPaged(
self._client, query, kwargs, page_iterator_class=SearchPageIterator
)

right?

Copy link
Member Author

Choose a reason for hiding this comment

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

Right, you can do that, but it sort of becomes a "six in one hand, half-dozen in the other" kind of thing. It's not better or worse, just different. Given that, I opted to keep it consistent with what was previously there.

scoring_statistics=scoring_statistics
)
if isinstance(select, list):
query.select(select)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,19 @@ async def search(self, search_text, **kwargs): # pylint:disable=too-many-locals
$skip to implement client-side paging of search results. If results are truncated due to
server-side paging, the response will include a continuation token that can be used to issue
another Search request for the next page of results.
:keyword scoring_statistics: A value that specifies whether we want to calculate scoring
statistics (such as document frequency) globally for more consistent scoring, or locally, for
lower latency. The default is 'local'. Use 'global' to aggregate scoring statistics globally
before scoring. Using global scoring statistics can increase latency of search queries.
Possible values include: "local", "global".
:paramtype scoring_statistics: str or ~azure.search.documents.models.ScoringStatistics
:keyword session_id: A value to be used to create a sticky session, which can help getting more
consistent results. As long as the same sessionId is used, a best-effort attempt will be made
to target the same replica set. Be wary that reusing the same sessionID values repeatedly can
interfere with the load balancing of the requests across replicas and adversely affect the
performance of the search service. The value used as sessionId cannot start with a '_'
character.
:paramtype session_id: str
:rtype: AsyncSearchItemPaged[dict]

.. admonition:: Example:
Expand Down Expand Up @@ -253,6 +266,8 @@ async def search(self, search_text, **kwargs): # pylint:disable=too-many-locals
select = kwargs.pop("select", None)
skip = kwargs.pop("skip", None)
top = kwargs.pop("top", None)
session_id = kwargs.pop("session_id", None)
scoring_statistics = kwargs.pop("scoring_statistics", None)

query_answer = kwargs.pop("query_answer", None)
query_answer_count = kwargs.pop("query_answer_count", None)
Expand Down Expand Up @@ -291,6 +306,8 @@ async def search(self, search_text, **kwargs): # pylint:disable=too-many-locals
select=select if isinstance(select, six.string_types) else None,
skip=skip,
top=top,
session_id=session_id,
scoring_statistics=scoring_statistics
)
if isinstance(select, list):
query.select(select)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,18 @@ def list_indexes(self, **kwargs):
# type: (**Any) -> ItemPaged[SearchIndex]
"""List the indexes in an Azure Search service.

:keyword select: Selects which top-level properties of the skillsets to retrieve. Specified as a
list of JSON property names, or '*' for all properties. The default is all
properties.
:paramtype select: list[str]
Copy link
Member

Choose a reason for hiding this comment

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

Is it a breaking change?

Copy link
Member Author

Choose a reason for hiding this comment

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

It shouldn't be, no. If you pass in a string, which was what was allowed but completely undocumented before, the join operation will simply result in that same string.

:return: List of indexes
:rtype: ~azure.core.paging.ItemPaged[~azure.search.documents.indexes.models.SearchIndex]
:raises: ~azure.core.exceptions.HttpResponseError

"""
kwargs["headers"] = self._merge_client_headers(kwargs.get("headers"))
if kwargs.get('select', None):
kwargs['select'] = ','.join(kwargs['select'])
# pylint:disable=protected-access
return self._client.indexes.list(
cls=lambda objs: [SearchIndex._from_generated(x) for x in objs], **kwargs
Expand Down Expand Up @@ -306,6 +312,10 @@ def get_synonym_maps(self, **kwargs):
# type: (**Any) -> List[SynonymMap]
"""List the Synonym Maps in an Azure Search service.

:keyword select: Selects which top-level properties of the skillsets to retrieve. Specified as a
list of JSON property names, or '*' for all properties. The default is all
properties.
:paramtype select: list[str]
:return: List of synonym maps
:rtype: list[~azure.search.documents.indexes.models.SynonymMap]
:raises: ~azure.core.exceptions.HttpResponseError
Expand All @@ -321,6 +331,8 @@ def get_synonym_maps(self, **kwargs):

"""
kwargs["headers"] = self._merge_client_headers(kwargs.get("headers"))
if kwargs.get('select', None):
kwargs['select'] = ','.join(kwargs['select'])
result = self._client.synonym_maps.list(**kwargs)
# pylint:disable=protected-access
return [SynonymMap._from_generated(x) for x in result.synonym_maps]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ def get_indexers(self, **kwargs):
# type: (**Any) -> Sequence[SearchIndexer]
"""Lists all indexers available for a search service.

:keyword select: Selects which top-level properties of the skillsets to retrieve. Specified as a
list of JSON property names, or '*' for all properties. The default is all
properties.
:paramtype select: list[str]
:return: List of all the SearchIndexers.
:rtype: `list[~azure.search.documents.indexes.models.SearchIndexer]`

Expand All @@ -174,6 +178,8 @@ def get_indexers(self, **kwargs):
:caption: List all the SearchIndexers
"""
kwargs["headers"] = self._merge_client_headers(kwargs.get("headers"))
if kwargs.get('select', None):
kwargs['select'] = ','.join(kwargs['select'])
result = self._client.indexers.list(**kwargs)
return result.indexers

Expand Down Expand Up @@ -390,6 +396,10 @@ def get_data_source_connections(self, **kwargs):
# type: (**Any) -> Sequence[SearchIndexerDataSourceConnection]
"""Lists all data source connections available for a search service.

:keyword select: Selects which top-level properties of the skillsets to retrieve. Specified as a
list of JSON property names, or '*' for all properties. The default is all
properties.
:paramtype select: list[str]
:return: List of all the data source connections.
:rtype: `list[~azure.search.documents.indexes.models.SearchIndexerDataSourceConnection]`

Expand All @@ -403,6 +413,8 @@ def get_data_source_connections(self, **kwargs):
:caption: List all the SearchIndexerDataSourceConnections
"""
kwargs["headers"] = self._merge_client_headers(kwargs.get("headers"))
if kwargs.get('select', None):
kwargs['select'] = ','.join(kwargs['select'])
result = self._client.data_sources.list(**kwargs)
# pylint:disable=protected-access
return [
Expand Down Expand Up @@ -465,6 +477,10 @@ def get_skillsets(self, **kwargs):
# type: (**Any) -> List[SearchIndexerSkillset]
"""List the SearchIndexerSkillsets in an Azure Search service.

:keyword select: Selects which top-level properties of the skillsets to retrieve. Specified as a
list of JSON property names, or '*' for all properties. The default is all
properties.
:paramtype select: list[str]
:return: List of SearchIndexerSkillsets
:rtype: list[~azure.search.documents.indexes.models.SearchIndexerSkillset]
:raises: ~azure.core.exceptions.HttpResponseError
Expand All @@ -480,6 +496,8 @@ def get_skillsets(self, **kwargs):

"""
kwargs["headers"] = self._merge_client_headers(kwargs.get("headers"))
if kwargs.get('select', None):
kwargs['select'] = ','.join(kwargs['select'])
result = self._client.skillsets.list(**kwargs)
return [SearchIndexerSkillset._from_generated(skillset) for skillset in result.skillsets] # pylint:disable=protected-access

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,18 @@ def list_indexes(self, **kwargs):
# type: (**Any) -> AsyncItemPaged[SearchIndex]
"""List the indexes in an Azure Search service.

:keyword select: Selects which top-level properties of the skillsets to retrieve. Specified as a
list of JSON property names, or '*' for all properties. The default is all
properties.
:paramtype select: list[str]
:return: List of indexes
:rtype: ~azure.core.async_paging.AsyncItemPaged[:class:`~azure.search.documents.indexes.models.SearchIndex`]
:raises: ~azure.core.exceptions.HttpResponseError

"""
kwargs["headers"] = self._merge_client_headers(kwargs.get("headers"))

if kwargs.get('select', None):
kwargs['select'] = ','.join(kwargs['select'])
# pylint:disable=protected-access
return self._client.indexes.list(
cls=lambda objs: [SearchIndex._from_generated(x) for x in objs], **kwargs
Expand Down Expand Up @@ -313,6 +318,10 @@ async def get_synonym_maps(self, **kwargs):
# type: (**Any) -> List[SynonymMap]
"""List the Synonym Maps in an Azure Search service.

:keyword select: Selects which top-level properties of the skillsets to retrieve. Specified as a
list of JSON property names, or '*' for all properties. The default is all
properties.
:paramtype select: list[str]
:return: List of synonym maps
:rtype: list[~azure.search.documents.indexes.models.SynonymMap]
:raises: ~azure.core.exceptions.HttpResponseError
Expand All @@ -328,6 +337,8 @@ async def get_synonym_maps(self, **kwargs):

"""
kwargs["headers"] = self._merge_client_headers(kwargs.get("headers"))
if kwargs.get('select', None):
kwargs['select'] = ','.join(kwargs['select'])
result = await self._client.synonym_maps.list(**kwargs)
# pylint:disable=protected-access
return [SynonymMap._from_generated(x) for x in result.synonym_maps]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ async def get_indexers(self, **kwargs):
# type: (**Any) -> Sequence[SearchIndexer]
"""Lists all indexers available for a search service.

:keyword select: Selects which top-level properties of the skillsets to retrieve. Specified as a
list of JSON property names, or '*' for all properties. The default is all
properties.
:paramtype select: list[str]
:return: List of all the SearchIndexers.
:rtype: `list[~azure.search.documents.indexes.models.SearchIndexer]`

Expand All @@ -175,6 +179,8 @@ async def get_indexers(self, **kwargs):
:caption: List all the SearchIndexers
"""
kwargs["headers"] = self._merge_client_headers(kwargs.get("headers"))
if kwargs.get('select', None):
kwargs['select'] = ','.join(kwargs['select'])
result = await self._client.indexers.list(**kwargs)
return result.indexers

Expand Down Expand Up @@ -393,6 +399,10 @@ async def get_data_source_connection(self, name, **kwargs):
# type: (str, **Any) -> SearchIndexerDataSourceConnection
"""Retrieves a data source connection definition.

:keyword select: Selects which top-level properties of the skillsets to retrieve. Specified as a
list of JSON property names, or '*' for all properties. The default is all
properties.
:paramtype select: list[str]
:param name: The name of the data source connection to retrieve.
:type name: str
:return: The SearchIndexerDataSourceConnection that is fetched.
Expand All @@ -406,6 +416,8 @@ async def get_data_source_connection(self, name, **kwargs):
:caption: Retrieve a SearchIndexerDataSourceConnection
"""
kwargs["headers"] = self._merge_client_headers(kwargs.get("headers"))
if kwargs.get('select', None):
kwargs['select'] = ','.join(kwargs['select'])
result = await self._client.data_sources.get(name, **kwargs)
# pylint:disable=protected-access
return SearchIndexerDataSourceConnection._from_generated(result)
Expand Down Expand Up @@ -453,6 +465,10 @@ async def get_skillsets(self, **kwargs):
# type: (**Any) -> List[SearchIndexerSkillset]
"""List the SearchIndexerSkillsets in an Azure Search service.

:keyword select: Selects which top-level properties of the skillsets to retrieve. Specified as a
list of JSON property names, or '*' for all properties. The default is all
properties.
:paramtype select: list[str]
:return: List of SearchIndexerSkillsets
:rtype: list[~azure.search.documents.indexes.models.SearchIndexerSkillset]
:raises: ~azure.core.exceptions.HttpResponseError
Expand All @@ -468,6 +484,8 @@ async def get_skillsets(self, **kwargs):

"""
kwargs["headers"] = self._merge_client_headers(kwargs.get("headers"))
if kwargs.get('select', None):
kwargs['select'] = ','.join(kwargs['select'])
result = await self._client.skillsets.list(**kwargs)
return [SearchIndexerSkillset._from_generated(skillset) for skillset in result.skillsets] # pylint:disable=protected-access

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,21 @@ class SearchIndexerDataSourceConnection(msrest.serialization.Model):
~azure.search.documents.models.DataDeletionDetectionPolicy
:keyword e_tag: The ETag of the data source.
:paramtype e_tag: str
:keyword identity: An explicit managed identity to use for this datasource. If not specified and
the connection string is a managed identity, the system-assigned managed identity is used. If
not specified, the value remains unchanged. If "none" is specified, the value of this property
is cleared.
:paramtype identity: ~azure.search.documents.indexes.models.SearchIndexerDataIdentity
:keyword encryption_key: A description of an encryption key that you create in Azure Key Vault.
This key is used to provide an additional level of encryption-at-rest for your datasource
definition when you want full assurance that no one, not even Microsoft, can decrypt your data
source definition in Azure Cognitive Search. Once you have encrypted your data source
definition, it will always remain encrypted. Azure Cognitive Search will ignore attempts to set
this property to null. You can change this property as needed if you want to rotate your
encryption key; Your datasource definition will be unaffected. Encryption with customer-managed
keys is not available for free search services, and is only available for paid services created
on or after January 1, 2019.
:paramtype encryption_key: ~azure.search.documents.indexes.models.SearchResourceEncryptionKey
"""

_validation = {
Expand All @@ -872,7 +887,9 @@ class SearchIndexerDataSourceConnection(msrest.serialization.Model):
"key": "dataDeletionDetectionPolicy",
"type": "DataDeletionDetectionPolicy",
},
'encryption_key': {'key': 'encryptionKey', 'type': 'SearchResourceEncryptionKey'},
"e_tag": {"key": "@odata\\.etag", "type": "str"},
'identity': {'key': 'identity', 'type': 'SearchIndexerDataIdentity'},
}

def __init__(self, **kwargs):
Expand All @@ -889,6 +906,8 @@ def __init__(self, **kwargs):
"data_deletion_detection_policy", None
)
self.e_tag = kwargs.get("e_tag", None)
self.encryption_key = kwargs.get("encryption_key", None)
self.identity = kwargs.get("identity", None)

def _to_generated(self):
if self.connection_string is None or self.connection_string == "":
Expand All @@ -905,6 +924,8 @@ def _to_generated(self):
data_change_detection_policy=self.data_change_detection_policy,
data_deletion_detection_policy=self.data_deletion_detection_policy,
e_tag=self.e_tag,
encryption_key=self.encryption_key,
identity=self.identity
)

@classmethod
Expand All @@ -925,6 +946,8 @@ def _from_generated(cls, search_indexer_data_source):
data_change_detection_policy=search_indexer_data_source.data_change_detection_policy,
data_deletion_detection_policy=search_indexer_data_source.data_deletion_detection_policy,
e_tag=search_indexer_data_source.e_tag,
encryption_key=search_indexer_data_source.encryption_key,
identity=search_indexer_data_source.identity
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
QueryLanguage,
QuerySpellerType,
QueryType,
SearchMode,
ScoringStatistics,
SearchMode
)
from .._search_client import odata

Expand All @@ -52,5 +53,6 @@
"QueryLanguage",
"QuerySpellerType",
"QueryType",
"ScoringStatistics",
"SearchMode",
)