I am looking at Azure Search for a message service. Very simplified, we have an Azure App Service (running .NET) and two tables on SQL Azure:
Message: Id, Subject, Body, [...]
MessageRecipient: Id, MessageId, UserId, [...]
One message has 1:N recipients.
I want an index to search the Subject and Body of Message, but the results must be filtered on the current user being a recipient of the message. I can't seem to find a good way to implement this so it scales well to high volumes. Returning all search results from the index and then filtering on UserId in my application would generate a lot of unnecessary overhead. And indexing each message duplicated for each UserId is even worse.
How would you best implement a recipient-filtered message search?
Thanks,
TGM
In similar situations I have utilized the Collection(Edm.String) data type in my search index. So an example document from your index would look something like this:
{
messageId : 1,
subject : "Why Azure Search is cool",
body: "Just because",
recipientIds : ["123", "456", "789"]
}
The recipientIds field is defined as type Collection(Edm.String) in the index schema.
Then you can use the "any" and "all" OData expressions to filter your searches. So, if you wanted to find messages sent to recipient id 123 your filter expression would look like this:
$filter=recipientIds/any(r: r eq '123')
See the Azure Search OData expression docs for more details.
Related
How do you structure a Azure POST REST call to match a value on a comma-separated list string?
For Example:
I want to search for "GWLAS" or "SAMGV" within the Azure field "ProductCategory".
The "ProductCategory" field in the documents will have a comma-separated value string such as "GWLAS, EXDEB, SAMGV, AMLKYC".
Any ideas?
If you use the default analyzer for your ProductCategory field (assuming it is searchable), it should word-break on commas by default. This means all you should need to do is search for the terms you're interested in and limit it to the right field:
POST /indexes/yourindex/docs/search?api-version=2016-09-01
{
"search": "GWLAS SAMGV",
"searchFields": [ "ProductCategory" ]
}
There are other ways to do this, but this is the simplest. If you already scope parts of your search query to other fields, here is how you can scope just the desired terms to ProductCategory:
POST /indexes/yourindex/docs/search?api-version=2016-09-01
{
"search": "(Name:\"Anderson John\"~3 OR Text:\"Anderson John\"~3) AND ProductCategory:GWLAS SAMGV",
"queryType": "full"
}
Please consult the Azure Search REST API documentation for details on other options you can set in the Search request. Also, this article will help you understand how Azure Search executes queries. You can find the reference for the full Lucene query syntax here.
The "Exact Search" fields use their own custom analyzer, while the Search fields use a language specific custom analyzer (built on MicrosoftStemmingTokenizerLanguage.French, for example).
I can't seem to use $filter for the "Exact Search" field, because $filter considers the entire field, and doesn't use the custom analyzer of the field.
Azure Search docs indicate this about field scoped queries.
"You can specify a fieldname:searchterm construction to define a fielded query operation, where the field is a single word, and the search term is also a single word"
There is no clear way on how to do this in Azure. We know we can use the searchFields parameter in our Azure Search Rest API calls to target specific fields, but how do we search ALL fields for 1 term while specifically searching some fields for specific terms, basically doing an “AND” between them?
This is possible using the Lucene query syntax.
Construct your query like this, where "chair" is the term to search for in all fields, and field1 and field2 are fields where you want to search for specific terms:
chair AND field1:something AND field2:else
In terms of how you use this in the REST API, just embed it in your search parameter. If you're using GET it looks like this (imagine it URL-encoded):
search=chair AND field1:something AND field2:else
If you're using POST, it goes in the request body and looks like this:
{
"search": "chair AND field1:something AND field2:else",
... (other parameters)
}
I am currently working with the Algolia search API and I am unable to figure out how I would limit the results by key value searching + query string. By this i mean this.
I have a list of properties.
Each property belongs to a client.
Within the application If i am looking at a client information card and I want to search for a property that client owns It would make more sense to limit the results to the client and then look for the query string.
I am using MongoDB as my DB and storing the client id as a sub document like so
//Property Document
{
_id : "randomID"
client : {
_id : "randomID",
name : "ClientName"
}
}
If you want to restrict the search to a specific client, I would go for facet filtering to restrict the search to that client only.
Add client._id in the attributesForFaceting in your index settings
Filter your searches with the facetFilters=client._id:MYCLIENTID query parameter
Then, you should also take a look at the Secured API keys which are able to encode such restriction in a secure way (so the end-user cannot patch the JS code and work-around the filtering).
There is parameter called restrictSearchableAttributes[link] to restrict, at query time, search to some attributes only. Nevertheless, in your case I think you'd get more accurate results by putting each client info into a different record (+ the info of the related document).
Folks, I was wondering what is the best way to model document and/or map functions that allows me "Not Equals" queries.
For example, my documents are:
1. { name : 'George' }
2. { name : 'Carlin' }
I want to trigger a query that returns every documents where name not equals 'John'.
Note: I don't have all possible names before hand. So the parameters in query can be any random text like 'John' in my example.
In short: there is no easy solution.
You have four options:
sending a multi range query
filter the view response with a server-side list function
using a CouchDB plugin
use the mango query language
sending a multi range query
You can request the view with two ranges defined by startkey and endkey. You have to choose the range so, that the key John is not requested.
Unfortunately you have to find the commit request that somewhere exists and compile your CouchDB with it. Its not included in the official source.
filter the view response with a server-side list function
Its not recommended but you can use a list function and ignore the row with the key John in your response. Its like you will do it with a JavaScript array.
using a CouchDB plugin
Create an additional index with e.g. couchdb-lucene. The lucene server has such query capabilities.
use the "mango" query language
Its included in the CouchDB 2.0 developer preview. Not ready for production but will be definitely included in the stable release.
How to find particular json document details from couchdb
For ex : Database name : employee_mgmt, in that database contains 50 json documents. So i want to find particular employee json documents ( Find by employee id ).
CouchDB does in it self not provide you with collections/buckets, hence all your documents are peers. It's up to you to provide meta-data e.g. by having a property $doctype with a value representing what kind of document it is. This is useful if you are writing maps and e.g. want to create a view (secondary index) returning something applicable only to employees.
Know, if you just want to query by _id you don't need the above. Just do a simple GET with an URI as: http://host:port/databasename/documentid
More information: http://docs.couchdb.org/en/1.6.1/api/document/common.html#get--db-docid
If you want to get a batch of documents matching many _id use the builtin index _all_docs http://docs.couchdb.org/en/1.6.1/api/database/bulk-api.html#post--db-_all_docs