When are index level tokenizers/tokenFilters/CharFilters used? - azure-cognitive-search

When are the index level tokenizers/tokenFilters/CharFilters used if each of the fields in the index definition already has a customer analayzer for both indexing & searching?
Ex:
Index indexDefiniton = new Index()
{
Name = myIndexName,
Fields = FieldBuilder.BuildForType<AzureIndexDocument>(),
Analyzers = new[]
{
new CustomAnalyzer()
{
Name = indexConstants.DefaultIndexAnalyzerName,
CharFilters = new[] {
CharFilterName.Create(indexConstants.SlashFilterName),
CharFilterName.Create(indexConstants.DashFilterName)
},
Tokenizer = TokenizerName.Whitespace,
TokenFilters = new[] { TokenFilterName.Lowercase},
},
new CustomAnalyzer()
{
Name = indexConstants.PrefixAnalyzerName,
Tokenizer = TokenizerName.Whitespace,
TokenFilters = new[] { TokenFilterName.Lowercase,
TokenFilterName.Stopwords,
},
},
new CustomAnalyzer()
{
Name = indexConstants.SearchTermAnalyzerName,
Tokenizer = TokenizerName.Whitespace,
TokenFilters = new[] { TokenFilterName.Lowercase }
},
new CustomAnalyzer()
{
Name = indexConstants.KeywordIndexAnalyzer,
Tokenizer = TokenizerName.Keyword,
TokenFilters = new[] { TokenFilterName.Lowercase , TokenFilterName.Trim }
}
},
TokenFilters = new List<TokenFilter>
{
new EdgeNGramTokenFilterV2
{
Name = indexConstants.PrefixCreatingTokenFilterName, MinGram = 1, MaxGram = 50
},
new WordDelimiterTokenFilter
{
Name = indexConstants.CatenateNumberFilterTokenFilterName ,
CatenateNumbers = true,
CatenateWords = true,
CatenateAll = true ,
PreserveOriginal = true
}
},
CharFilters = new List<CharFilter>
{
new PatternReplaceCharFilter(indexConstants.SlashFilterName, s_Slash, s_Space),
new PatternReplaceCharFilter(indexConstants.DashFilterName, s_Dash, s_Space),
new PatternReplaceCharFilter(indexConstants.UnderScoreFilterName, s_UnderScore, s_Space),
new PatternReplaceCharFilter(indexConstants.RoundBracketOpeningFilterName, s_RoundBracketOpening, s_Space),
new PatternReplaceCharFilter(indexConstants.RoundBracketClosingFilterName, s_RoundBracketClosing, s_Space)
},
};
Let's say all of the fields declared in the index definition either use keyword/prefix/default analyzer as declared above for indexing and searchAnalayzer for searching. Then when will the TokenFilter (EdgeNGramTokenFilterV2, WorddelimitTokenFilter), CharFilters declared as part of the index used here ?

You need to explicitly refer to the custom analyzers in the field where you want them to be used (either by setting the "analyzer" property on that field, or the "indexAnalyzer" and "searchAnalyzer", to the name of the custom analyzer you want to use). If you simply create a custom analyzer but don't actually use it in any field, it will not be used.

Related

Adding Google Classroom ID based on user enrollment code

I have a spreadsheet where a user can list classes and Google Classroom enrollment codes, represented by the array userClassCodes. This array is allowed to contain blank values when the range contains blank cells. This array is represented in the following way:
[ ['class name 01', 'class code 01'], ['class name 02', 'class code 02'], ...]
I am using the Google Classroom API to get a list of the sheet user's enrollment codes and course IDs. I would like to iterate through the userClassCodes array and add the class ID to the array when there is a matching class code in the API response. If there is no match, I would like to preserve the entry in the array and add a blank value for the course ID.
I am having trouble properly constructing an array that will achieve the desired output. Here is my current code:
function googleClassroomImport() {
var userClassCodes = SpreadsheetApp.getActive().getRange("Sheet1!A1:B25").getValues();
var newArray = [];
var options = {
teacherId: 'me',
courseStates: 'ACTIVE',
pageSize: 50
};
var response = Classroom.Courses.list(options);
response.courses.forEach(function (course) {
for (let i = 0; i < userClassCodes.length; i++) {
if (userClassCodes[i][1] == course.enrollmentCode) {
newArray.push([userClassCodes[i][0], userClassCodes[i][1], course.id]);
}
else {
newArray.push([userClassCodes[i][0], userClassCodes[i][1], ""]);
}
}
});
console.log(newArray);
}
Try this:
function googleClassroomImport() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0");
const rg = sh.getRange("A1:B25");
const vs = rg.getValues().filter(r => r[0] && r[1]).filter(e => e);
const arr = vs.map(r => r[1]);
var options = { teacherId: 'me', courseStates: 'ACTIVE', pageSize: 50 };
var response = Classroom.Courses.list(options);
response.courses.forEach(course => {
let idx = arr.indexOf(course.enrollmentCode);
if (~idx) {
vs[idx].push(course.id);
} else {
vs[idx].push('');
}
});
console.log(newArray);
}

How to change JSON API label into number in .net

So currently I'm using react-simple-map to make a map that with marker. It required this json format:
[{
"coordinates":{
"0":139.6917,
"1":35.6480
},
"name":"Tokyo",
},
{
"coordinates":{
"0":101.9758,
"1":4.2105
},
"name":"Malaysia",
}]
Then I'm trying to change the label in .net like this:
public IQueryable<Object> GetCoordination()
{
return from a in _awContext.SalesTerritories
join p in _awContext.Coordination
on a.TerritoryId equals p.TerritoryID
select new
{
id = a.TerritoryId,
coordinates = new
{
'0' = p.Lat,
'1' = p.Long,
},
name = a.Name,
countryRegionCode = a.CountryRegionCode,
salesYtd = a.SalesYtd,
salesLastYear = a.SalesLastYear,
costYtd = a.CostYtd,
costLastYear = a.CostLastYear,
};
}
What happen is the 0 & 1 have error.
Is there anyway to make it integer.
you should not have array key
{
"coordinates": [0.1234,1.2345]
}
Cheers !

Lambda expressions to JSON array

List<string> _columns = new List<string>() { "Kurator", "Filial", "Klient", "Saldo", "Docs", "no_Docs", "Change", "Status" };
var columns = cols.Select(p => new {
data = p.ColumnName });
Tis gives me an array of objects JsonResult: data:Kurator, data:Filial etc.
Here is data = constant. How i can use it dynamically from another List???
So i need data from two list of objects
List<string> list1 = new List<string>() { "lst1-1", "lst1-2", "lst1-3" };
List<string> list2 = new List<string>() { "lst2-1", "lst2-2", "lst2-3" };
var columns = cols.Select(p => new {
lst1-1= lst2-1 });
To get in return Json(columns, JsonRequestBehavior.AllowGet);
columns = array of (lst1-1:lst2-1,lst1-2:lst2-1, lst1-3:lst2-1)
i`m already break my head!!!
try this:
var columns = from l1 in list1.Select((val, index) => new { val, index })
from l2 in list2.Select((val, index) => new { val, index })
where l1.index == l2.index
select l1.val + " : " + l2.val;

Telerik ComboBox with picture

I need a picture in combobox but I have only path
var files = Url.Content("~/Content/skin/Simple.png");
#(Html.Telerik().ComboBox()
.Name("ComboBox")
.BindTo(files.Select(f => new SelectListItem { Selected = false, Text = f.ToString(), Value = "" }))
)
thank you but if I need to show all pictures in folder
string searchFolder = Url.Content("~/Content/skin/");
var filters = new[] { "jpg", "jpeg", "png", "gif", "tiff", "bmp" };
var files = Some Class.GetFilesFrom(searchFolder, filters, false);
there are my full code
controller
public ActionResult Combo()
{
return View();
}
model
public class Combo
{
public static string[] GetFilesFrom(string searchFolder, string[] filters, bool isRecursive)
{
var filesFound = new List<String>();
var searchOption = isRecursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
foreach (var filter in filters)
{
filesFound.AddRange(Directory.GetFiles(searchFolder, String.Format("*.{0}", filter), searchOption));
}
return filesFound.ToArray();
}
}
and View
#using TETRA.RS.WWW.UI.Models
#{
string searchFolder = Url.Content("~/Content/skin/");
var filters = new[] { "jpg", "jpeg", "png", "gif", "tiff", "bmp" };
var files = Combo.GetFilesFrom(searchFolder, filters, false);
}
#(Html.Telerik().ComboBox()
.Name("ComboBox")
.BindTo(files.Select(f => new SelectListItem { Selected = false, Text = f, Value = "" }))
)
And I see only full path in combobox
And I do not Know how many pictures in a folder
There are different ways of adding images to an item selectable from a radcombobox, each has their benefits and the most suitable can only be defined by your requirements.
The easiest way is to assign a value to the ImageUrl attribute.
(Telerik Documentation: http://www.telerik.com/help/aspnet-ajax/combobox-appearance-item-images.html)
Alternatively you could modify the item template. (Telerik Demo: http://demos.telerik.com/aspnet-ajax/combobox/examples/functionality/templates/defaultcs.aspx)
I have used Kendo UI
I have a folder with pictures and I don't Know how much there are
I need to get all the pictures and use in comboBox
Method finds all pictures
public static string[] GetFilesFrom(string searchFolder, string[] filters, bool isRecursive)
{
var filesFound = new List<string>();
var searchOption = isRecursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
foreach (var filter in filters)
{
filesFound.AddRange(Directory.GetFiles(searchFolder, String.Format("*.{0}", filter), searchOption));
}
return filesFound.Select(Path.GetFileName).ToArray();
}
SettingsController
public ActionResult Theme()
{
return View();
}
public JsonResult ThemeJson()
{
string searchFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Content\\themes\\skin");
var filters = new[] { "jpg", "jpeg", "png", "gif", "tiff", "bmp" };
var files = Tools.GetFilesFrom(searchFolder, filters, false);
return Json(files.Select(f => new { Id = f, Name = Path.GetFileNameWithoutExtension(f) }));
}
and View
#using Kendo.Mvc.UI
#(Html.Kendo().ComboBox()
.Name("customers")
.DataTextField("Name")
.DataValueField("Id")
.HtmlAttributes(new { })
.DataSource(source => source.Read(read => read.Action("ThemeJson", "Settings").Type(HttpVerbs.Post)))
.Filter("startswith")
.Height(300)
.Template("<img src=\"" + Url.Content("~/Content/themes/skin/") + "${data.Id}\" alt=\"${data.Id}\" />" +
"<dl>" +
"Name theme: ${ data.Name }" +
"</dl>")
)
also you need add reference kendo.all.min.js and Kendo.Mvc.UI

Using javascript prototype function to initialise variable in 'this' context

I'm finding it difficult to explain in words, so here's a snippet of code I'm trying out but Firefox/firebug goes into tailspin!
I'm trying to follow this and this as a guide. What I'm trying to do here is
new MyObject.Method('string',optionsArray);
optionsArray items are iterated and saved using the prototype function Set()
if(typeof(MyObj) == 'undefined') MyObj= {};
MyObj.Method = function initialise(id,options)
{
this.id = id;
this.options = options;
this.properties ={};
for (var i = 0; i < this.options.length; i++) // =>options.length=2 (correct)
{
var obj = this.options[i];
//get the keynames, pass with values to Set() to update properties
for (var keys in obj)
{
console.log(keys); //=> correctly prints 'property1' and 'currentValue'
this.Set(keys,obj); //=> this is i guess where it enters a loop?
}
}
}
//sets properties
MyObj.Method.prototype.Set = function (name, value)
{
this.properties[name.toLowerCase()] = value;
}
and in my html page script block, i have
window.onload = function () {
var options = [
{ property1: {
show: true,
min: 0,
max: 100
}
},
{
currentValue: {
show: true,
colour: 'black'
}
}
];
var myObj = new MyObj.Method('someDivId',options);
}
please advise if I'm over complicating the code. I think checking for hasOwnProperty would help.
This should be a cleaner way of achieving what you want:
function MyObj(id, options) { // a function that will get used as the constructor
this.id = id;
this.options = options;
this.properties = {};
this.set(options); // call the set method from the prototype
}
MyObj.prototype.set = function(options) { // set the options here
for(var i = 0, l = options.length; i < l; i++) {
var obj = this.options[i];
for(var key in obj) {
if (obj.hasOwnProperty(key)) { // this will exclude stuff that's on the prototype chain!
this.properties[key] = obj[key];
}
}
}
return this; // return the object for chaining purposes
// so one can do FooObj.set([...]).set([...]);
};
var test = new MyObj('simeDivId', [...]); // create a new instance of MyObj
test.set('bla', [...]); // set some additional options
Note: For what hasOwnProperty is about please see here.
I made a declaration for MyObj and removed the function name initialise since you're obviously declaring this function to be a property of MyObj. Your final code will then be like below, and that runs for me just fine. Please note that you cannot actually call the function until after you declare the prototype function because else the object will have no notion of the Set function.
var MyObj = {};
MyObj.Method = function (id,options)
{
this.id = id;
this.properties ={};
for (var i = 0; i < options.length; i++) // =>options.length=2 (correct)
{
var obj = options[i];
//get the keynames, pass with values to Set() to update properties
for (var keys in obj)
{
console.log(keys); //=> correctly prints 'property1' and 'currentValue'
this.Set(keys,obj); //=> this is i guess where it enters a loop?
}
}
}
MyObj.Method.prototype.Set = function (name, value)
{
this.properties[name.toLowerCase()] = value;
}
var options = [
{ property1: {
show: true,
min: 0,
max: 100
}
},
{
currentValue: {
show: true,
colour: 'black'
}
}
];
var myObj = new MyObj.Method('someDivId',options);
var MyObj = {};
MyObj.Method = function initialise(id,options) {
this.id = id;
this.options = options;
this.properties = {};
for (var i = 0; i < this.options.length; i++)
{
var obj = this.options[i];
for (var keys in obj) {
this.Set(keys,obj[keys]);
//*fix obj => obj[keys]
// (and it should be singular key rather then keys
}
}
console.log(this.properties) // will output what you want
}
//sets properties
MyObj.Method.prototype.Set = function (name, value) {
this.properties[name.toLowerCase()] = value;
}
var options = [{
property1: {
show: true,
min: 0,
max: 100
}
},{
currentValue: {
show: true,
colour: 'black'
}
}];
var myObj = new MyObj.Method('someDivId',options);
this should work problem is you had your myObj = new MyObj... outside your onload event and options was out of its scope as it was declared as private variable to the anonymous function bound to the onload event.
I've fixed also the way you was copying the values to the properties as it doubled the names of the property and made it a bit messy.

Resources