Azure Search - querying for ampersand character - azure-cognitive-search

I'm trying to find all records which contain & symbol, which is reserved. I'm using search, not $filter.
According to documentation, it can not be escaped with \%, and should be escaped as HTML url part to %26.
Trying SDK and Search explorer to find any options on how to search, but with no succeed:
&
*&*
*%26*
%26
\%26
UPD
Document example:
{
"test": "Hello & World"
Search query: search=%26&searchFields=test&$select=test
UPD 2
public class MyType
{
[System.ComponentModel.DataAnnotations.Key]
[IsFilterable]
public string Id { get; set; }
[IsSearchable, IsSortable]
public string Test { get; set; }
}
class Program
{
private static SearchServiceClient CreateSearchServiceClient()
{
string searchServiceName = "XXXXXX";
string adminApiKey = "XXXXXXX";
var serviceClient = new SearchServiceClient(searchServiceName, new SearchCredentials(adminApiKey));
return serviceClient;
}
static void Main(string[] args)
{
var client = CreateSearchServiceClient();
var def = new Microsoft.Azure.Search.Models.Index
{
Name = "temp-test-reserved1",
Fields = FieldBuilder.BuildForType<MyType>()
};
client.Indexes.Create(def);
var c = client.Indexes.GetClient("temp-test-reserved1");
var actions = new IndexAction<MyType>[]
{
IndexAction.Upload(new MyType{ Id = "1", Test = "Hello & World" }),
IndexAction.Upload(new MyType{ Id = "2", Test = "& test start" }),
IndexAction.Upload(new MyType{ Id = "3", Test = "test end &" })
};
c.Documents.Index(IndexBatch.New(actions));
}
}
search=%26&searchFields=Test&$select=Test

You likely can't find & because it's being removed at indexing and query time, since it's considered to be punctuation by the default analyzer. This article has more details on lexical analysis in Azure Cognitive Search. If you need to preserve ampersands while still tokenizing text on whitespace boundaries, you'll need to create a custom analyzer.

In the search explorer field on the Azure portal try the query &search=%26(as shown below)
In the SDK, only if you have set the UseHttpGetForQueries parameter to true, you would need to think of URL encoding the '&' character. By default, this parameter is set to false in which case you don't need to encode it.
More documentation about escaping/encoding here

Related

MongoDB Compass returns all rows when I run a filter

I am trying to run a filter in MongoDB Compass and it returns all rows instead of the row that I am looking for. I can run the filter on example databases that are similar to my database without any problem.
https://i.stack.imgur.com/IBivJ.png
Here is the code that I am using to add records and select from them.
public class NoSQLDataAccess
{
// Create an instance of data factory
public NoSQLDataFactory noSQLDataFactory;
public List<dynamic> DocumentDetails { get; set; }
private IMongoCollection<dynamic> collection;
private BsonDocument bsonDocument = new BsonDocument();
public NoSQLDataAccess() { }
public void TestNoSQL()
{
MongoClient client;
IMongoDatabase database;
string connectionString = ConfigurationManager.AppSettings["NoSQLConnectionString"];
client = new MongoClient(connectionString);
database = client.GetDatabase("TestDatabase");
collection = database.GetCollection<dynamic>("TestCollection");
// Insert
List<Layer> layers = new List<Layer>();
layers.Add(new Layer { LayerId = 117368, Description = "BOOTHLAYER" });
layers.Add(new Layer { LayerId = 117369, Description = "DRAWINGLAYER" });
layers.Add(new Layer { LayerId = 117370, Description = "LAYER3" });
List<Element> elements = new List<Element>();
elements.Add(new Element { ElementId = 9250122, Type = "polyline" });
elements.Add(new Element { ElementId = 9250123, Type = "polyline" });
List<dynamic> documentDetails = new List<dynamic>();
documentDetails.Add(new DrawingDTO { Layers = layers, Elements = elements });
collection.InsertMany(documentDetails);
List<FilterDetails> filterDetails = new List<FilterDetails>();
filterDetails.Add(new FilterDetails { Type = "layers.id", Value = "117368" });
foreach (FilterDetails detail in filterDetails)
{
bsonDocument.Add(new BsonElement(detail.Type, detail.Value));
}
List<dynamic> results = collection.Find(bsonDocument.ToBsonDocument()).ToList();
}
}
I have been able to get the result I need with MongoDB shell but I have not been able to replicate the results in C#.
Here is the solution in MongoDB shell:
db.TestCollection.find({"layers.id": 117368}, {_id:0, layers: {$elemMatch: {id: 117368}}}).pretty();
I have found a post that is similar to my question that works for them. The C# code that I attached is how I will access it after I get it working properly. I use MongoDB Compass to test finds/inserts/updates/deletes.
Retrieve only the queried element in an object array in MongoDB collection

NHibernate Convert query to async query

I'm looking at async-ifying some of our existing code. Unfortunately my experience with NHibernate is lacking. Most of the NHibernate stuff has been easy, considering NHibernate 5 has a lot of support for async. I am, however, stuck.
Originally, we do something like this using our Dependency Injection:
private readonly IRepository repository;
public MovieRepository(IRepository repository)
{
this.repository = repository;
}
public Movie Get(int id)
{
return (from movie in repository.Query<Movie>()
select new Movie
{
ID = movie.ID,
Title = movie.Title,
Genre = new Genre
{
ID = movie.Genre.ID,
Name = movie.Genre.Name,
},
MaleLead = movie.MaleLead,
FemaleLead = movie.FemaleLead,
}).FirstOrDefault();
}
//Repository Query method in Repository.cs
public IQueryable<TEntity> Query<TEntity>() where TEntity : OurEntity
{
session = session.OpenSession();
return from entity in session.Query<TEntity>() select entity;
}
This works great for our current uses. We write things this way to maintain control over our queries, especially related to more complex objects, ensuring we get back exactly what we need.
I've tried a few things, like making the Query method return a Task< List< TEntity>> and using the ToListAsync() method, however because I am returning it as that kind of list I cannot query on it.
I'm sure I've missed something. If anyone can help me out, I would appreciate it.
You need to use FirstOrDefaultAsync in this case.
public async Task<Movie> Get(int id)
{
return await (from movie in repository.Query<Movie>()
select new Movie
{
ID = movie.ID,
Title = movie.Title,
Genre = new Genre
{
ID = movie.Genre.ID,
Name = movie.Genre.Name,
},
MaleLead = movie.MaleLead,
FemaleLead = movie.FemaleLead,
}).FirstOrDefaultAsync();
}
Add this using statement to your file
using NHibernate.Linq;
Then you can change your method to
public async Task<Movie> Get(int id)
{
return await (from movie in repository.Query<Movie>()
select new Movie
{
ID = movie.ID,
Title = movie.Title,
Genre = new Genre
{
ID = movie.Genre.ID,
Name = movie.Genre.Name,
},
MaleLead = movie.MaleLead,
FemaleLead = movie.FemaleLead,
}).FirstOrDefaultAsync();
}
NB: This is only available from NHibernate 5
Addendum:
The code you have in Repository.cs can be simplified to something like this:
//Repository Query method in Repository.cs
public IQueryable<TEntity> Query<TEntity>() where TEntity : OurEntity
{
//session = session.OpenSession(); //this is obviously wrong, but it's beside the point
var session = sessionFactory.OpenSession();
return session.Query<TEntity>(); //the fix
}

Lucene use taxonomy and DocValues facets together

There are many examples of the use of facets based on the taxonomy index and on DocValues. But I need use as a hierarchy of categories (taxonomy) and Range queries (NumericDocValuesField) together.
For example DrillSideways :
DrillSideways ds = new DrillSideways (searcher, config, taxoReader);
DrillSideways.DrillSidewaysResult result = ds.search (q, topScoreDocCollector);
The second parameter of ds.search() is TopScoreDocCollector.
FacetsCollector created inside ds.search() and not possible to pass this collector to ds.search(). Pass MultiCollector.wrap (FacetsCollector, TopScoreDocCollector) as second parameter in ds.search() is not correct(?). However FacetsCollector need to build facets that are not available in the taxonomy index:
Facets facetsTime = new LongRangeFacetCounts (..., FacetsCollector, ...);
facetsTime.getTopChildren (...);
Also list result.facets contain null value, which refers to DocValues ​​facet.
Maybe you have a working example how use taxonomy and DocValues ​​facets in DrillSideways together.
DrillSideways assumes that you use either TaxonomyFacets or SortedSetDocValuesFacets exclusively. If this is not the case, you can subclass DrillSideways and override the buildFacetsResult method to build the final Facets however you like. You will get the FacetsCollector for the DrillDownQuery and two arrays with the sideways FacetCollectors and dims, for every dim you have added to the DrissSideways.
Here is an example:
public class MyDrillSideways extends DrillSideways {
public MyDrillSideways(IndexSearcher searcher, FacetsConfig config, TaxonomyReader taxoReader) {
super(searcher, config, taxoReader);
}
#Override
protected Facets buildFacetsResult(FacetsCollector drillDowns, FacetsCollector[] drillSideways, String[] drillSidewaysDims) throws IOException {
String longRangeFacetDim = "mySpecialLongRangeDim";
Facets drillDownFacets = new FastTaxonomyFacetCounts(taxoReader, config, drillDowns);
boolean foundLongRangeInDrillSideways = false;
Map<String, Facets> drillSidewaysFacets = new HashMap<>();
if (drillSideways != null) {
for (int i = 0; i < drillSideways.length; i++) {
String sidewaysDim = drillSidewaysDims[i];
FacetsCollector drillSideway = drillSideways[i];
Facets sidewaysFacets;
if (sidewaysDim.equals(longRangeFacetDim)) {
foundLongRangeInDrillSideways = true;
sidewaysFacets = new LongRangeFacetCounts(...,drillSideway,...);
} else {
sidewaysFacets = new FastTaxonomyFacetCounts(taxoReader, config, drillSideway);
}
drillSidewaysFacets.put(sidewaysDim, sidewaysFacets);
}
}
if (!foundLongRangeInDrillSideways) {
Facets facetsTime = new LongRangeFacetCounts(..., FacetsCollector, ...);
drillSidewaysFacets.put(longRangeFacetDim, facetsTime);
}
return new MultiFacets(drillSidewaysFacets, drillDownFacets);
}
}

how can set parameter values for params string[] parameter

I am required to produce the following address
http://example.com/Content/Details?cid=34&query=%D8%AA%D8%AD&positions%5B0%5D=true&positions%5B0%5D=false&positions%5B1%5D=false&positions%5B2%5D=false
this url after decode is :
http://example.com/Content/Details?cid=32&query=تحلیل&positions[0]=true&positions[0]=false&positions[1]=false&positions[2]=false
My action method contains the following parameters
public ActionResult Details(
string cid, string query, int? page, int id = 0, params string[] positions)
{
if(positions != null)
{
ViewBag.Title = positions[0];
ViewBag.Description = positions[1];
ViewBag.KeyWord = positions[2];
}
}
But when I set the parameters required for the positions parameter I get an error :
In fact i cant use positions[0] , positions[1] and positions[2] !!!
my cshtml page :
#{ title
#Html.CheckBox("positions[0]", ViewBag.Title as string)
description
#Html.CheckBox("positions[1]", ViewBag.Description as string)
keyword
#Html.CheckBox("positions[2]", ViewBag.KeyWord as string)
}
#Html.PagedListPager(Model, page => Url.Action("Details", new {cid = ViewBag.currentFilter, query= ViewBag.currentSearchString , positions[0]=ViewBag.title , positions[1]=ViewBag.Description ,position[2]=ViewBag.KeyWord,page }))
how can i set values for positions parameter in cshtml page ?
How can i set position[0] ,positions[2] and positions[3] ... i want know this just
the rest of my code is correct
please help me
You should read them in your controller and set them in ViewBag or ViewData:
ViewData["positons_0"] = Request.QueryString["positions[0]"];
ViewData["positons_1"] = Request.QueryString["positions[1]"];
// etc ...
Then you will be able to use them in your view also.
But I would suggest that you remove the square brackets from your querystring if possible. These are reserverd characters for IP v6 address literals (see here) and this is why you cannot use them in MVC. Your url should be:
http://example.com/Content/Details?cid=32&query=تحلیل&positions=true&positions=false&positions=false&positions=false
In this way you will be able to use it in both your controller:
public ActionResult Details(string cid, string query, int? page, int id = 0, string[] positions)
{
// ....
}
... and view:
#foreach(string position in Model.positions) // example
{
// ....
}

windows phone create database with items

I am building a simple application for windows phone. I want to create a database and want to have several (lets say 10) items in the database. I am a beginner and every tutorial that i have seen is sth about adding items in the database on button "add" or sth like that. I don't need that, because I want to have several item that are in the database, ready for the user to use them. How can I achieve this? Please write to me in a clear way, because I am still a beginner. If you can provide some links of examples or tutorials, that would be great. Thank u!
If you need to have the preloaded DB then you can Add a sqlCe DB in your application and populate the db with your seed Data.
then you can copy the DB file to your ISO Store while your Constructor of DBContext is invoked.
public Moviadb1DataContext (string connectionString) : base(connectionString)
{
IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication();
if (!iso.FileExists("Moviadb1.sdf"))
{
MoveReferenceDatabase();
}
if (!DatabaseExists())
CreateDatabase();
}
public static void MoveReferenceDatabase()
{
// Obtain the virtual store for the application.
IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication();
// Create a stream for the file in the installation folder.
using (Stream input = Application.GetResourceStream(new Uri("Moviadb1.sdf", UriKind.Relative)).Stream)
{
// Create a stream for the new file in isolated storage.
using (IsolatedStorageFileStream output = iso.CreateFile("Moviadb1.sdf"))
{
// Initialize the buffer.
byte[] readBuffer = new byte[4096];
int bytesRead = -1;
// Copy the file from the installation folder to isolated storage.
while ((bytesRead = input.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
output.Write(readBuffer, 0, bytesRead);
}
}
}
}
you can also add some seed data instead of moving the reference DB if you have very small amount of Data.
public ListenDataDataContext (string connectionString) : base(connectionString)
{
if (!DatabaseExists())
{
CreateDatabase();
List<Audiables> PreLoads = new List<Audiables>();
PreLoads.Add(new Audiables { Category = 1, Name = "I want To Eat", AudioLocation = "Sounds/Food/1_IwantToEat.wma", ImageLocation = "Images/Food/1_IwantToEat.jpg" });
PreLoads.Add(new Audiables { Category = 1, Name = "I want To Drink", AudioLocation = "Sounds/Food/1_IwantToDrink.wma", ImageLocation = "Images/Food/1_IwantToDrink.jpg" });
PreLoads.Add(new Audiables { Category = 2, Name = "I want A Ticket", AudioLocation = "Sounds/Travel/1_IwantATicket.wma", ImageLocation = "Images/Travel/1_IwantATicket.jpg" });
PreLoads.Add(new Audiables { Category = 2, Name = "I want To Sit", AudioLocation = "Sounds/Travel/1_IwantToSit.wma", ImageLocation = "Images/Travel/1_IwantToSit.jpg" });
PreLoads.Add(new Audiables { Category = 3, Name = "How Much Is That", AudioLocation = "Sounds/Shopping/1_HowMuchIsThat.wma", ImageLocation = "Images/Shopping/1_HowMuchIsThat.jpg" });
PreLoads.Add(new Audiables { Category = 3, Name = "Please Take the Money", AudioLocation = "Sounds/Shopping/1_PleaseTakeTheMoney.wma", ImageLocation = "Images/Shopping/1_PleaseTakeTheMoney.jpg" });
Audiables.InsertAllOnSubmit(PreLoads);
this.SubmitChanges();
}
}
Happy app making :)
Best way is to check the "Local Database Sample" in the Windows Phone Code Samples!

Resources