Elasticsearch painless sorting null_pointer_error - elasticsearch

I'm trying to create a sorting script with painless, filtering nested documents.
The reason I'm doing this with a script, is because I need to emulate a COALESCE statement.
My documents have titles stored like:
{
title: [
{
type: MainTitle,
value: [
{
language: eng,
label: The title
},
{
language: ger,
label: Das title
}
]
},
{
type: AvailabilityTitle,
value: [
{
language: eng,
label: New thing!
}
]
}
]
}
title and title.value are nested documents.
I want to sort documents primarily by their english MainTitle and by their german MainTitle only if no english MainTitle exists - even if the german title gave a higher score.
I'm trying to simply sort by the english MainTitle first to try it out and this is the script:
def source = params._source;
def titles = source.title;
if (titles != null && titles.length > 0) {
for(int i=0; i < titles.length; i++) {
def t = titles[i];
if (t.type == 'MainTitle') {
def values = t.value;
if (values != null && values.length > 0) {
for (int j = 0; j < values.length; j++) {
def v = values[j];
if (v.language == 'eng') {
return v.label;
}
}
}
}
}
}
return \"\";
For some reason I'm getting a null_pointer_exception
"script_stack": [
"if (values != null && values.length > 0) { ",
" ^---- HERE"
],
I don't get how values can be null at that point since I'm specifically checking for null just before it.

The null_pointer_exception is thrown, not because values is null, but because values does not have a method/function called length. That is because for some reason values is an ArrayList even though titles earlier is an Array. Apparently they both have the method/function size() so I can just use that.
So this works:
def source = params._source;
def titles = source.title;
if (titles != null && titles.size() > 0) {
for(int i=0; i < titles.size(); i++) {
def t = titles[i];
if (t.type == 'MainTitle') {
def values = t.value;
if (values != null && values.size() > 0) {
for (int j = 0; j < values.size(); j++) {
def v = values[j];
if (v != null && v.language == 'fin') {
return v.label;
}
}
}
}
}
}
return '';

Related

Troubles with for loop and Range

var colRange = getRange("Sheet1!G2:G200")
logger.log(colRange)
logger.log(colRange[0])
for(var i = 0; i < colRange.length; i++) {
if(activeCell.getColumn() == 7 && activeCell.getRow() == colRange[i] && ss.getActiveSheet().getName()=="Sheet1") {
newValue=e.value;
oldValue=e.oldValue;
if(!e.value) {
activeCell.setValue("");
}
else {
if (!e.oldValue) {
activeCell.setValue(newValue);
}
else {
activeCell.setValue(oldValue+', '+newValue);
}
}
}
}
Could anybody help with the for loop. Need it to check every row of column G to allow multiple drop down selections. If I replace colRange[i] with the specific row it does work. I assume I need to loop through each range G2, G3, G4, etc
Please explain what you are trying to
It's hard to figure out what you are trying to accomplish with you code but this is my best guess
function onEdit(e) {
const sh = e.range.getSheet();
if (e.range.columnStart == 7 && e.range.rowStart > 1 && sh.getName() == "Sheet1") {
if (!e.value) {
e.range.setValue("");//doesn't make sense it's already null
} else if (!e.oldValue) {
e.range.setValue(e.value);
} else {
e.range.setValue(oldValue + ', ' + newValue);
}
}
}

Filter on Tree or Nested Data

I have seen in one of the issues "Filter on Tree or Nested Data #1562" Oli has mentioned that
Hey #fr0z3nfyr
Filtering is supported on tree child nodes since version 4,2
Cheers
Oli :)
I am unable to find any example or the code to search nested data.
My code works perfectly fine for flat tables, but with nested tables it only works for the root node.
//data - the data for the row being filtered
//filterParams - params object passed to the filter
var match = false;
for (var key in data) {
if (data[key] != null) {
if ((data[key]).indexOf(filterParams.value) != -1) {
match = true;
}
}
}
return match;
}
function updateFilter(){
if ($("#filter-field").val() == "All Columns") {
table.setFilter(matchAny,{ value: $("#filter-value").val()});
} else {
table.setFilter($("#filter-field").val(), "like", $("#filter-value").val());
}
//var filter = $("#filter-field").val() == "All Columns" ? matchAny : $("#filter-field").val() ;
}```
Oli could you please point me to an example where Nested data filtering is supported
I was able to solve this, but by re-setting table data with filtered value and also the tree structure is not maintained in the filtered list. I can maintain the tree structure with some changes in code, but this flat looks more like what I needed once filtering is done.
// This method iterates through the dataRows and its tree children and call a recursive function which creates the filtered table data.
function updateFilter() {
var filtertableData = [];
table.getRows().filter(function (row) {
var rootData = row.getData();
rootData._children = [];
matchData(rootData, filtertableData);
var childRows = row.getTreeChildren();
searchForChildRows(rootData,childRows,filtertableData);
while (childRows.length != 0) {
for (var i = 0; i < childRows.length; i++) {
var childrow = childRows[i];
var childData = childrow.getData();
childData._children = [];
childRows = childrow.getTreeChildren();
searchForChildRows(childData,childRows,filtertableData);
}
}
});
table.setData(filtertableData);
}
function matchData(rootData, filtertableData, childdata) {
if (typeof childdata === "undefined") {
for (var key in rootData) {
console.log(key);
console.log(allVisibleCBSCols);
if (rootData[key] != null && typeof rootData[key] == 'string' && allVisibleCBSCols.includes(key)) {
if ((rootData[key]).indexOf($("#filter-value-Project").val()) != -1) {
filtertableData.push(rootData);
break;
}
}
}
} else {
for (var key in childdata) {
if (childdata[key] != null && typeof childdata[key] == 'string' && allVisibleCBSCols.includes(key)) {
if ((childdata[key]).indexOf($("#filter-value-Project").val()) != -1) {
//rootData._children.push(childdata);
filtertableData.push(childdata);
break;
}
}
}
}
}
function searchForChildRows(rootData,childRows,filtertableData) {
for (var i = 0; i < childRows.length; i++) {
var childrow = childRows[i];
var childData = childrow.getData();
childData._children = [];
matchData(rootData,filtertableData,childData);
}
}

Backbone JS: Validating required nested attributes/models?

If I have a Backbone model who's defaults object looks like this:
defaults {
"id" : null
"name" : null,
"url" : null,
"admin" : {
"id" : null,
"email" : null
}
}
is there a recommended way to validate the presence of something like admin[id]? We've written a method that makes the attempt, but it keeps puking (especially on new model creation) on null values, or if data is fetched from our DB with null values that are expected to be required (we are laying this app on top of existing data).
Here's our method for validating the presence of required fields:
validatePresence = function(requiredAttrs, submittedAttrs, errorsArr) {
var regex = new RegExp(/[a-zA-Z0-9_]+|(?=\[\])/g),
attrStack = null,
val = null,
name = null;
for( var l = requiredAttrs.length; --l >= 0; ) {
attrStack = requiredAttrs[l].match(regex);
val = submittedAttrs[attrStack.shift()];
while(attrStack.length > 0) {
console.log(requiredAttrs[l]);
val = val[attrStack.shift()];
}
if( val === undefined ) { continue; }
name = requiredAttrs[l];
if( val === null || !val.length) {
if( !errorsArr[name] ) {
errorsArr[name] = [];
}
errorsArr[name].push("Oops, this can't be empty");
}
}
return errorsArr;
}
And here's the way we call it from within a BB model:
validate: function(attrs) {
var requiredAttributes = ["name","admin[id]"],
errors = {};
errors = validatePresence(requiredAttributes, attrs, errors);
}
That method likes to choke on things like "admin[id]". Any help is apprecaited.
If you're not dead set on the bracket notation for your required attributes, you could draw some inspiration from this Q&A to simplify your validation.
Let's add a helper method to _ to extract the value of a given attribute:
_.findprop = function(obj, path) {
var args = path.split('.'), i, l=args.length;
for (i=0; i<l; i++) {
if (!obj.hasOwnProperty(args[i]))
return;
obj = obj[args[i]];
}
return obj;
}
Your validate method can then be rewritten as:
validate: function(attrs) {
var requiredAttributes = ["name","admin.id"],
errors = {}, i, l, v, attr;
for (i=0, l=requiredAttributes.length; i<l; i++) {
attr = requiredAttributes[i];
v = _.findprop(attrs, attr);
//checks if the value is truthy, to be adapted to your needs
if (v) continue;
errors[attr] = errors[attr] || [];
errors[attr].push("Oops, this can't be empty");
}
return errors;
}
And a demo http://jsfiddle.net/FrtHb/2/

Windows Phone 7 UserExtendedProperties

After being directed here:
http://msdn.microsoft.com/en-us/library/microsoft.phone.info.userextendedproperties.getvalue%28v=VS.92%29.aspx
I tried the following code on my sideloaded application. All that was written out was the 000001 value.
I knew that would be the case in the emulator, but I was hoping to get a real value when it was on my phone. Any ideas?
int ANIDLength = 32;
int ANIDOffset = 2;
string result = string.Empty;
object anid;
if (UserExtendedProperties.TryGetValue("ANID", out anid))
{
if (anid != null && anid.ToString().Length >= (ANIDLength + ANIDOffset))
{
result = anid.ToString().Substring(ANIDOffset, ANIDLength);
}
else
{
result = "000001";
}
}
You need to remove 1 from the calculation of your length check to account for the substring operation working on a zero based index:
if (anid != null && anid.ToString().Length >= (ANIDLength + ANIDOffset - 1))
This works on my machine:
private string GetAnid()
{
object anidValue;
int ANIDLength = 32;
int ANIDOffset = 2;
if (UserExtendedProperties.TryGetValue("ANID", out anidValue))
{
if (anidValue != null && anidValue.ToString().Length >= (ANIDLength + ANIDOffset - 1))
{
return anidValue.ToString().Substring(ANIDOffset, ANIDLength);
}
else
{
return "???";
}
}
else
{
return "???";
}
}

Count the number of "holes" in a bitmap

Consider a MxN bitmap where the cells are 0 or 1. '1' means filled and '0' means empty.
Find the number of 'holes' in the bitmap, where a hole is a contiguous region of empty cells.
For example, this has two holes:
11111
10101
10101
11111
... and this has only one:
11111
10001
10101
11111
What is the fastest way, when M and N are both between 1 and 8?
Clarification: diagonals are not considered contiguous, only side-adjacency matters.
Note: I am looking for something that takes advantage of the data format. I know how to transform this into a graph and [BD]FS it but that seems overkill.
You need to do connected component labeling on your image. You can use the Two-pass algorithm described in the Wikipedia article I linked above. Given the small size of your problem, the One-pass algorithm may suffice.
You could also use BFS/DFS but I'd recommend the above algorithms.
This seems like a nice use of the disjoint-set data structure.
Convert the bitmap to a 2d array
loop through each element
if the current element is a 0, merge it with the set of one its 'previous' empty neighbors (already visited)
if it has no empty neighbors, add it to its own set
then just count the number of sets
There may be advantages gained by using table lookups and bitwise operations.
For example whole line of 8 pixels may be looked up in 256 element table, so number of holes in a field 1xN is got by single lookup. Then there may be some lookup table of 256xK elements, where K is number of hole configurations in previous line, contatining number of complete holes and next hole configuration. That's just an idea.
I wrote an article describe the answer on Medium https://medium.com/#ahmed.wael888/bitmap-holes-count-using-typescript-javascript-387b51dd754a
but here is the code, the logic isn't complicated and you can understand it without reading the article.
export class CountBitMapHoles {
bitMapArr: number[][];
holesArr: Hole[] = [];
maxRows: number;
maxCols: number;
constructor(bitMapArr: string[] | number[][]) {
if (typeof bitMapArr[0] == 'string') {
this.bitMapArr = (bitMapArr as string[]).map(
(word: string): number[] => word.split('').map((bit: string): number => +bit))
} else {
this.bitMapArr = bitMapArr as number[][]
}
this.maxRows = this.bitMapArr.length;
this.maxCols = this.bitMapArr[0].length;
}
moveToDirection(direction: Direction, currentPosition: number[]) {
switch (direction) {
case Direction.up:
return [currentPosition[0] - 1, currentPosition[1]]
case Direction.down:
return [currentPosition[0] + 1, currentPosition[1]]
case Direction.right:
return [currentPosition[0], currentPosition[1] + 1]
case Direction.left:
return [currentPosition[0], currentPosition[1] - 1]
}
}
reverseDirection(direction: Direction) {
switch (direction) {
case Direction.up:
return Direction.down;
case Direction.down:
return Direction.up
case Direction.right:
return Direction.left
case Direction.left:
return Direction.right
}
}
findNeighbor(parentDir: Direction, currentPosition: number[]) {
let directions: Direction[] = []
if (parentDir === Direction.root) {
directions = this.returnAvailableDirections(currentPosition);
} else {
this.holesArr[this.holesArr.length - 1].positions.push(currentPosition)
directions = this.returnAvailableDirections(currentPosition).filter((direction) => direction != parentDir);
}
directions.forEach((direction) => {
const childPosition = this.moveToDirection(direction, currentPosition)
if (this.bitMapArr[childPosition[0]][childPosition[1]] === 0 && !this.checkIfCurrentPositionExist(childPosition)) {
this.findNeighbor(this.reverseDirection(direction), childPosition)
}
});
return
}
returnAvailableDirections(currentPosition: number[]): Direction[] {
if (currentPosition[0] == 0 && currentPosition[1] == 0) {
return [Direction.right, Direction.down]
} else if (currentPosition[0] == 0 && currentPosition[1] == this.maxCols - 1) {
return [Direction.down, Direction.left]
} else if (currentPosition[0] == this.maxRows - 1 && currentPosition[1] == this.maxCols - 1) {
return [Direction.left, Direction.up]
} else if (currentPosition[0] == this.maxRows - 1 && currentPosition[1] == 0) {
return [Direction.up, Direction.right]
} else if (currentPosition[1] == this.maxCols - 1) {
return [Direction.down, Direction.left, Direction.up]
} else if (currentPosition[0] == this.maxRows - 1) {
return [Direction.left, Direction.up, Direction.right]
} else if (currentPosition[1] == 0) {
return [Direction.up, Direction.right, Direction.down]
} else if (currentPosition[0] == 0) {
return [Direction.right, Direction.down, Direction.left]
} else {
return [Direction.right, Direction.down, Direction.left, Direction.up]
}
}
checkIfCurrentPositionExist(currentPosition: number[]): boolean {
let found = false;
return this.holesArr.some((hole) => {
const foundPosition = hole.positions.find(
(position) => (position[0] == currentPosition[0] && position[1] == currentPosition[1]));
if (foundPosition) {
found = true;
}
return found;
})
}
exec() {
this.bitMapArr.forEach((row, rowIndex) => {
row.forEach((bit, colIndex) => {
if (bit === 0) {
const currentPosition = [rowIndex, colIndex];
if (!this.checkIfCurrentPositionExist(currentPosition)) {
this.holesArr.push({
holeNumber: this.holesArr.length + 1,
positions: [currentPosition]
});
this.findNeighbor(Direction.root, currentPosition);
}
}
});
});
console.log(this.holesArr.length)
this.holesArr.forEach(hole => {
console.log(hole.positions)
});
return this.holesArr.length
}
}
enum Direction {
up = 'up',
down = 'down',
right = 'right',
left = 'left',
root = 'root'
}
interface Hole {
holeNumber: number;
positions: number[][]
}
main.ts file
import {CountBitMapHoles} from './bitmap-holes'
const line = ['1010111', '1001011', '0001101', '1111001', '0101011']
function main() {
const countBitMapHoles = new CountBitMapHoles(line)
countBitMapHoles.exec()
}
main()
function BitmapHoles(strArr) {
let returnArry = [];
let indexOfZ = [];
let subarr;
for(let i=0 ; i < strArr.length; i++){
subarr = strArr[i].split("");
let index = [];
for(let y=0 ; y < subarr.length; y++){
if(subarr[y] == 0)
index.push(y);
if(y == subarr.length-1)
indexOfZ.push(index);
}
}
for(let i=0 ; i < indexOfZ.length; i++){
for(let j=0; j<indexOfZ[i].length ; j++){
if(indexOfZ[i+1] && (indexOfZ[i][j]==indexOfZ[i+1][j] || indexOfZ[i+1].indexOf(indexOfZ[i][j])))
returnArry.indexOf(strArr[i]) < 0 ? returnArry.push(strArr[i]): false;
if(Math.abs(indexOfZ[i][j]-indexOfZ[i][j+1])==1)
returnArry.indexOf(strArr[i]) < 0 ? returnArry.push(strArr[i]): false;
}
}
return returnArry.length;
}
// keep this function call here
console.log(BitmapHoles(readline()));
function findHoles(map) {
let hole = 0;
const isHole = (i, j) => map[i] && map[i][j] === 0;
for (let i = 0; i < map.length; i++) {
for (let j = 0; j < map[i].length; j++) {
if (isHole(i, j)) {
markHole(i, j);
hole++;
}
}
}
function markHole(i, j) {
if (isHole(i, j)) {
map[i][j] = 2;
markHole(i, j - 1);
markHole(i, j + 1);
markHole(i + 1, j);
markHole(i - 1, j);
}
}
return hole;
}

Resources