Can elasticsearch with node, update only a certain field without rewrite? - javascript

My document has a field that looks like this:
_source:
...
"produto_tags" : [
{
"id_produto_cor" : "1623153806",
"tags" : []
},
{
"id_produto_cor" : "875623985732",
"tags": []
},
{...}
...
I need to insert on this field another Object without rewrite the entire produto_tags
data to be inserted:
{
"id_produto_cor" : "312411",
"tags": []
},
and my final document will looks like this:
_source:
...
"produto_tags" : [
{
"id_produto_cor" : "1623153806",
"tags" : []
},
{
"id_produto_cor" : "875623985732",
"tags": []
},
{
"id_produto_cor" : "312411",
"tags": []
}
]
Im using NODE js, I`m using this but it rewrites what I put :
const query = {
doc: {
nome_relatorio: nome_relatorio,
produto_tags: produto_tags,
referencia_tags: referencia_tags,
}
};
return await esClient.update({
index: indexName,
body: query,
id: id,
method: 'post',
type: typeDoc,
})

1. You can use update_by_query api
POST <index_name>/_update_by_query
{
"script": {
"source": "ctx._source.produto_tags.add(params.product)",
"params": {
"product": {
"product_id": "1004600287",
"tags": []
}
}
},
"query": {
"match_all": {} --> select the document
}
}
2. Update api
POST <index_name>/_update/<doc_id>
{
"script": {
"source": "ctx._source.produto_tags.add(params.product)",
"lang": "painless",
"params": {
"product": {
"product_id": "11",
"tags": []
}
}
}
}

Related

Put JSON data inside another object of the same JSON

I need to put the images that are on "included" into "data:{relationships: { field_imagen: { data" but the problem is that i just managed to put only the first image into every index using map and find
noticiasImages.forEach(function(data: { relationships: { field_imagen: {data: {id:any}}}} ) {
var nestedArray = noticiasData.map((noticiasImages: { id: any; }) => noticiasImages == noticiasData);
data = nestedArray && noticiasImages || noticiasData;
});
And this is my json (example node)
{
"data": [
"relationships": {
"field_imagen": {
"data": [
{
"type": "file--file",
"id": "dba917f0-b80f-45ed-a569-69f2ba2b482d",
}
],
}
]
},
this is the included object, who is in the same level as data
"included": [
"attributes": {
"drupal_internal__fid": 8798,
"langcode": "es",
"filename": "_DSC6472 - copia.jpg",
"uri": {
"value": "public:\/\/2019-11\/_DSC6472 - copia.jpg",
"url": "\/sites\/default\/files\/2019-11\/_DSC6472%20-%20copia.jpg"
},
},
,
Expected Result:
"data": [
"relationships": {
"type": "node--actualidad_institucional",
"id": "71514647-af49-4136-8a28-9563d133070a",
"field_imagen": {
"data": [
{
"type": "file--file",
"id": "dba917f0-b80f-45ed-a569-69f2ba2b482d",
"uri": {
"value": "public:\/\/2019-11\/_DSC6472 - copia.jpg",
"url": "\/sites\/default\/files\/2019-11\/_DSC6472%20-%20copia.jpg"
},
}
}
},
I put the uri from included into field_imagen. Tried to resolve like that, but it just put only the first image of the Array from the included object in every node:
showNoticias() {
this.frontService.getNoticias()
.subscribe((data: Noticias) => {
this.noticiasImages = Array.from(data.included);
this.noticiasData = Array.from(data.data);
let noticiasImages = this.noticiasImages.map((data: {id: any}) => data.id);
let noticiasData = this.noticiasData.map((data:{relationships: { field_imagen: { data: { id: any; }}}}) => data.relationships.field_imagen.data.id);
noticiasImages.forEach(function(data: { relationships: { field_imagen: {data: {id:any}}}} ) {
var nestedArray = noticiasData.map((noticiasImages: { id: any; }) => noticiasImages == noticiasData);
data = nestedArray && noticiasImages || noticiasData;
});
console.log(data);
});
}
Hope you can help me, thanks!
UPDATE: tried that but didnt work like expected
let merged = data.data.map((data:{relationships: { field_imagen: { data: any }}}) => Object.assign({}, noticiasImages));
console.log(data)
console.log(merged)
Sometimes using regular for loops are a better option. Using map with objects that have that many properties can get confusing. And using forEach will not give you access to the i index of the iteration in the loop, which makes things easier in this case.
for (let i = 0; i < obj.included.length; i++) {
let uri = obj.included[i].attributes.uri;
obj.data[i].relationships.field_imagen.data[0] = {
...obj.data[i].relationships.field_imagen.data[0],
...uri
}
}
console.log(obj)
Output:
{
"data": [
{
"relationships": {
"field_imagen": {
"data": [
{
"type": "file--file",
"id": "dba917f0-b80f-45ed-a569-69f2ba2b482d",
"value": "public://2019-11/_DSC6472 - copia.jpg",
"url": "/sites/default/files/2019-11/_DSC6472%20-%20copia.jpg"
}
]
}
}
}
],
"included": [
{
"attributes": {
"drupal_internal__fid": 8798,
"langcode": "es",
"filename": "_DSC6472 - copia.jpg",
"uri": {
"value": "public://2019-11/_DSC6472 - copia.jpg",
"url": "/sites/default/files/2019-11/_DSC6472%20-%20copia.jpg"
}
}
}
]
}

LogicApp/JavaScript - Split JSON data to multiple objects and arrays

I have below JSON data coming from source system into my Logic App:
[
{
"project":"abc",
"assignees":"123,456"
},
{
"project":"xyz",
"assignees":"123,468"
}
]
I want to split the "assignees", create arrays within objects, and produce below final output:
[
{
"metadata":{
"type":"project"
},
"name":"Project ABC",
"assignee":[
{
"metadata":{
"type":"assignment"
},
"employeeId":"123"
},
{
"metadata":{
"type":"assignment"
},
"employeeId":"123"
}
]
},
{
"metadata":{
"type":"project"
},
"name":"Project ABC",
"assignee":[
{
"metadata":{
"type":"assignment"
},
"employeeId":"123"
},
{
"metadata":{
"type":"assignment"
},
"employeeId":"468"
}
]
}
]
Can this be achieved in Logic App only? If not, can this be achieved using inline JavaScript code and how?
I don't know anything about LogicApp or how it works, but if all you want is javascript code that can make this transformation you can do something like this:
const src=[
{
"project":"abc",
"assignees":"123,456"
},
{
"project":"xyz",
"assignees":"123,468"
}
]
const transformed=src.map(entry=>({
"metadata":{type:"project"},
name:"Project "+entry.project.toUpperCase(),
assignee:entry.assignees.split(",").map(assignee=>({
metadata:{type:"assignment"},
emplyeeId:assignee
}))
}))
I initialize a variable named source to store same data source with yours.
And here provide a sample of inline javascript code for your reference:
var source = workflowContext.actions.Initialize_variable.inputs.variables[0].value;
var result = [];
source.forEach(sItem=>{
var resultItem = {
"metadata":{
"type":"project"
},
"name":"Project " + sItem.project.toUpperCase()
}
var assignee = [];
var assigneesSplit = sItem.assignees.split(",");
assigneesSplit.forEach(item=>{
var assigneItem = {
"metadata":{
"type":"assignment"
},
"employeeId":item
}
assignee.push(assigneItem);
});
resultItem.assignee = assignee;
result.push(resultItem);
});
return result;
After running the logic app, we can get the result data like:
[
{
"metadata": {
"type": "project"
},
"name": "Project ABC",
"assignee": [
{
"metadata": {
"type": "assignment"
},
"employeeId": "123"
},
{
"metadata": {
"type": "assignment"
},
"employeeId": "456"
}
]
},
{
"metadata": {
"type": "project"
},
"name": "Project XYZ",
"assignee": [
{
"metadata": {
"type": "assignment"
},
"employeeId": "123"
},
{
"metadata": {
"type": "assignment"
},
"employeeId": "468"
}
]
}
]
It seems there are some mistakes in your expected data sample(such as the second project name and the second employeeId in first assignee field). If they are not typo, please let me know, I will modify my js inline code to implement your expected json data.

Dynamically update key in array of objects + mongoose

I wouldnt be surprised if this has been asked before but I have not found a working example.
Basically I have a set of Boolean data inside of an array of objects and I would like to reuse my API routes/logic to update array of objects dynamically
Data Example:
{
"_id": 1,
"posts": [
{ "_id": d323d32, "published": true, "homepage": false, (...moreBooleanData) },
{ "_id": ffwfwfwc, "published": true, "homepage": false, (...moreBooleanData) },
{ "_id": fdscsdad, "published": true, "homepage": false, (...moreBooleanData) }
]
}
Mongoose Query
await Project.findOneAndUpdate(
{ _id: 1 },
{ $set: { "posts.$[el].published": isChecked } },
{
arrayFilters: [{ "el._id": postid }],
new: true
}
)
The problem is in this line "posts.$[el].published": isChecked. Here I have the key published hard coded but I would like to have this key dynamic so I can grab it from the body of my post request
const { DYNAMIC_KEY , isChecked } = req.body
"posts.$[el].$[DYNAMIC_KEY]": isChecked`
I have tried formatting the $set string with backticks, building it outside the query and passing it as 1 variable all without success. Any ideas?
You can achieve this using bracket notation:
router.post("/project/:id/:postid", async (req, res) => {
const { isChecked, dynamicKey } = req.body;
let set = `posts.$[el].${dynamicKey}`;
console.log(set);
const result = await Project.findOneAndUpdate(
{ _id: req.params.id },
{ $set: { [set]: isChecked } },
{
arrayFilters: [{ "el._id": req.params.postid }],
new: true
}
);
res.send(result);
});
I have a project document with these 3 posts:
{
"_id" : ObjectId("5def81070066dc23e05b816e"),
"posts" : [
{
"_id" : ObjectId("5def81070066dc23e05b8171"),
"published" : true,
"homepage" : false
},
{
"_id" : ObjectId("5def81070066dc23e05b8170"),
"published" : true,
"homepage" : false
},
{
"_id" : ObjectId("5def81070066dc23e05b816f"),
"published" : true,
"homepage" : false
}
],
"__v" : 0
}
I send a post request to my router ../project/5def81070066dc23e05b816e/5def81070066dc23e05b8170 with this body:
{
"isChecked": false,
"dynamicKey": "published"
}
The result is like this: ( post's (with id 5def81070066dc23e05b8170) published value is updated to false)
{
"_id": "5def81070066dc23e05b816e",
"posts": [
{
"_id": "5def81070066dc23e05b8171",
"published": true,
"homepage": false
},
{
"_id": "5def81070066dc23e05b8170",
"published": false,
"homepage": false
},
{
"_id": "5def81070066dc23e05b816f",
"published": true,
"homepage": false
}
],
"__v": 0
}

Looping through an array of objects

I have the array of objects called res and am trying to loop through and organize the objects based on having one href, one method, and in some cases multiple schema, as with:
href: '/questions/{id}'
My issue is when I have multiple schema, if the current object I am in has '$schema' I want to check if the next object in the array also has '$schema'. If it does then I want to label the current schema object, requestSchema and the next object will be called responseSchema. But if the next object does not contain '$schema' then the current object will be labeled responseSchema.
I want to take res and turn it into
[{
"resource": "/questions",
"verb": "GET",
"schemaResponse": {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"data": {
"type": "array",
"items": [{
"type": "object",
"properties": {
"question": {
"type": "string",
"enum": [
"Favourite programming language?"
]
},
"published_at": {
"type": "string",
"enum": [
"2014-11-11T08:40:51.620Z"
]
},
"url": {
"type": "string",
"enum": [
"/questions/1"
]
},
"choices": {
"type": "array",
"items": [{
"type": "object",
"properties": {
"choice": {
"type": "string",
"enum": [
"Javascript"
]
},
"url": {
"type": "string",
"enum": [
"/questions/1/choices/1"
]
},
"votes": {
"type": "number",
"enum": [
2048
]
}
},
"required": [
"choice",
"url",
"votes"
],
"additionalProperties": false
}]
}
},
"required": [
"question",
"published_at",
"url",
"choices"
],
"additionalProperties": false
}]
}
},
"required": [
"data"
]
}
}, {
"resource": "/questions/{id}",
"verb": "GET",
"schemaRequest": {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"id": {
"type": "number"
}
},
"required": [
"id"
]
},
"schemaResponse": {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"question": {
"type": "string",
"enum": [
"Favourite programming language?"
]
},
"published_at": {
"type": "string",
"enum": [
"2014-11-11T08:40:51.620Z"
]
},
"url": {
"type": "string",
"enum": [
"/questions/1"
]
},
"choices": {
"type": "array",
"items": [{
"type": "object",
"properties": {
"choice": {
"type": "string",
"enum": [
"Javascript"
]
},
"url": {
"type": "string",
"enum": [
"/questions/1/choices/1"
]
},
"votes": {
"type": "number",
"enum": [
2048
]
}
},
"required": [
"choice",
"url",
"votes"
],
"additionalProperties": false
}]
}
},
"required": [
"question",
"published_at",
"url",
"choices"
],
"additionalProperties": false
}
}
]
Everything works except for in the case of needing to have a request schema and a response schema.
const lodash = require('lodash');
var res = [
{ href: '/questions' },
{ method: 'GET' },
{ '$schema': 'http://json-schema.org/draft-04/schema#',
type: 'object',
properties: { data: [Object] },
required: [ 'data' ] },
{ href: '/questions/{id}',
hrefVariables: { element: 'hrefVariables', content: [Object] } },
{ method: 'GET',
headers: { element: 'httpHeaders', content: [Object] } },
{ '$schema': 'http://json-schema.org/draft-04/schema#',
type: 'object',
properties: { id: [Object] },
required: [ 'id' ] },
{ '$schema': 'http://json-schema.org/draft-04/schema#',
type: 'object',
properties:
{ question: [Object],
published_at: [Object],
url: [Object],
choices: [Object] },
required: [ 'question', 'published_at', 'url', 'choices' ] } ]
var arr = [];
var arrFinal = [];
var result = {};
for (var key = 0; key < res.length; key++) {
console.log(res[key]);
console.log(key);
var found = false;
for(var i = 0; i < arr.length; i++) {
//console.log((lodash.has(res[key], 'href')));
//console.log((lodash.has(res[key-1], '$schema')));
if ((lodash.has(arr[i], 'href'))) {
found = true;
break;
}
}
if ((lodash.has(res[key], '$schema')) && (lodash.has(res[key-1], '$schema'))) {
console.log('here');
result.schemaResponse = res[key];
result = lodash.omit(result, ['headers', 'properties', 'hrefVariables', 'required', 'href', 'method']);
break;
}
if((found === true) && (lodash.has(res[key], '$schema'))) {
var result = {};
console.log('there')
var combinedKeys = arr.reduce(function(a, item) {
Object.keys(item).map(function(key) {
if(key === 'href'){
result.resource = item[key];
}
if(key === 'method'){
result.verb = item[key];
} else {
result[key] = item[key];
}
});
return result;
}, {});
arr = [];
if((lodash.has(res[key+1], '$schema'))){
result.schemaRequest = res[key];
} else {
result.schemaResponse = res[key];
result = lodash.omit(result, ['headers', 'properties', 'hrefVariables', 'required', 'href', 'method']);
arrFinal.push(result);
result = {};
}
}
else {
console.log('hmmm');
var object = res[key];
arr.push(object);
}
}
var string = JSON.stringify(arrFinal, null, ' ')
console.log(arrFinal)
Based on this:
My issue is when I have multiple schema, if the current object I am in has '$schema' I want to check if the next object in the array also has '$schema'. If it does then I want to label the current schema object, requestSchema and the next object will be called responseSchema. But if the next object does not contain '$schema' then the current object will be labeled responseSchema.
and this (from my comment on your question):
Your question was a little unclear (I'd suggest proofreading it again and breaking up some of the run-on sentences). Are you saying that when you evaluate if ((lodash.has(res[key], '$schema')) && (lodash.has(res[key-1], '$schema'))) the value res[key-1] is always undefined?. So basically the 2nd if block never executes
Here is some pseudo-code to work into your code:
for ( var nIdx, crnt, next, key = 0, m = res.length; key < m; key++ ){
crnt = res[ key ]
next = res[ key + 1 ]
//do your checking here based on the existence of 'next'
if (next){ .... }
}
I'd test this on a simple loop and log the values of crnt and next to see if you're actually getting the expected results. If they are as expected, you can adjust your code to use those values instead of trying to access them dynamically with res[ key ] further down in your code.
I dunno, what the issue really is with your code, but this will be more readable at the least and will probably illuminate your error.

jstree, json, ajax: Recursive Search and Select

I have jstree setup to load all content via ajax and json. Is it possible for the script to execute my ajax/json url and keep sub-searching when possible, if it finds it open all sub nodes until its visible and select it (.jstree-clicked). And is such a feature built in, if not know any where I could start with this? I am not the most fluent at javascript.
Here is my setup:
$("#jstFormMirror").jstree({
"types" : {
"types" : {
"default" : {
"select_node" : function(e) {
this.toggle_node(e);
return true;
}
}
}
},
"ui" : {
"select_limit" : 1,
"selected_parent_close" : "select_parent"
},
"json_data" : {
"progressive_unload" : true,
"ajax" : {
"url" : "/back-end/json/categories.json",
"data" : function (n) {
return { id : n.attr ? n.attr("id") : 0 };
}
}
},
"plugins" : [ "themes", "json_data", "types", "ui" ],
"core": {
"animation": 100
}
}).bind("select_node.jstree", function(event, data) {
$("#category").val($(".jstree-clicked").parent().attr("rel"));
})
And he is a typical json response when the script loads a node:
[
{
"attr": {
"id": "87"
},
"data": {
"title": "Bevel Clusters-Over 350 Designs",
"attr": {
"href": "#",
"rel": "658"
}
},
"state": "closed"
},
{
"attr": {
"id": "394"
},
"data": {
"title": "Bevels, Straight Lines-Over 210 Shapes & Sizes",
"attr": {
"href": "#",
"rel": "321"
}
},
"state": "closed"
}
]
I want to execute:
$("#jstFormCategories").jstree("search", ID_HERE);
For this, DefiantJS is excellent (http://defiantjs.com).
This lib extends the global object JSON with the method "search" and enables you to search a JSON structure with XPath expressions.
To understand how easy XPath (which is a standardised query language) is, check out this tool;
http://www.defiantjs.com/#xpath_evaluator
Here is a working fiddle;
http://jsfiddle.net/hbi99/vV43F/
var data = [
{
"attr": {
"id": "87"
},
"data": {
"title": "Bevel Clusters-Over 350 Designs",
"attr": {
"href": "#",
"rel": "658"
}
},
"state": "closed"
},
{
"attr": {
"id": "394"
},
"data": {
"title": "Bevels, Straight Lines-Over 210 Shapes & Sizes",
"attr": {
"href": "#",
"rel": "321"
}
},
"state": "closed"
}
],
res = JSON.search( data, '//*[id=394]/../data' );
console.log( res[0].title );

Categories