Elastic Search delete a single element inside a field on _source - javascript

i`m trying to delete a element inside a field of my elastic field, current, I have this struct of data:
I need in my NODE application to delete a single element from produto_tags getting the id_produto_cor,
for example:
{
"_index" : "relatorio_recebimento_produto_hml",
"_type" : "_doc",
"_id" : "54XZ9HAB4DHa2O1nQlpk",
"_score" : 1.0,
"_source" : {
"id_usuario" : 1408,
"data_criacao" : "2020-03-19T22:10:40.465Z",
"produto_tags" : [
{
"id_produto_cor" : "2489664268",
"tags" : [ ]
},
{
"id_produto_cor" : "1000045010",
"tags" : [ ]
},
{
"id_produto_cor" : "1004600287",
"tags" : [ ]
},
{
"id_produto_cor" : "1032013410",
"tags" : [ ]
},
{
"id_produto_cor" : "2468436987",
"tags" : [ ]
}
],
"referencia_tags" : [ ],
"nome_relatorio" : "teste"
}
}
XDELETE
{
query: {
match: {
produto_tags.id_produto_cor: 489664268
}
}
}
I would expect my data to be like:
"_index" : "relatorio_recebimento_produto_hml",
"_type" : "_doc",
"_id" : "xYVD5XAB4DHa2O1ndFo1",
"_score" : 1.0,
"_source" : {
"id_usuario" : 1376,
"data_criacao" : "2020-03-16T21:32:46.369Z",
"produto_tags" : [
{
"id_produto_cor" : "1000045010",
"tags" : [ ]
},
{
"id_produto_cor" : "1004600287",
"tags" : [ ]
},
{
"id_produto_cor" : "1032013410",
"tags" : [ ]
},
{
"id_produto_cor" : "2468436987",
"tags" : [ ]
}
],
"referencia_tags" : { },
"nome_relatorio" : "teste"
}
},
...
This is my final structure
zzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzz

You can use _update_by_query
POST /index102/_update_by_query
{
"script":{
"source":"ctx._source.produto_tags.remove('1029831004')"
},
"query":{
"match_all":{} --> modify query to target specific documents
--> match_all will execute script on all documents
}
}
Query for changed structure:
iterate through produto_tags, match with specific value and store the matched object in an array (list). Then iteratate through list and remove the object from produto_tags
POST /<index_name>/_update_by_query
{
"script":{
"source":"if(ctx._source.produto_tags.size()==0) {return;} def list=[]; for(product in ctx._source.produto_tags) { if (product['id_produto_cor'] ==params.product_id){list.add(product)}} if(list.size()==0) return; for(d in list){ctx._source.produto_tags.remove(ctx._source.produto_tags.indexOf(d))}",
"params" : {
"product_id" : "2468436987"
}
},
"query":{
"match_all":{} --> to select specific documents
}
}

Related

How to find data on MongoDB by passing part of array objects

I tried to create an API for filtering the products by sending an array of objects as filters.
this is my Product schema:
const mongoose = require("mongoose");
const { s, rs, rn, rref, ref } = require("../utils/mongo");
let schema = new mongoose.Schema(
{
user: rref("user"),
name: rs,
description: s,
images: [s],
price: rn,
category: ref("category"),
filters: [
{
parent: ref("filter"),
value: s,
name: s,
},
],
subFilter: [
{
parent: s,
value: s,
title: s,
},
],
},
{ timestamps: true }
);
module.exports = mongoose.model("product", schema);
and this one is what I want to send as body to the API
{
category: '62445c3d922d127512867245'
filters: [
{ name: 'filter name 1', value: '62445c3d922d127512861236' },
{ name: 'filter name 2', value: '62445c3d922d127512861458' },
.....
]
}
as you see I want to filter my products based on category Id and an array of filter objects. I tried to write this query but it return an empty array.
this is my query:
filter: async (req, res) => {
try {
const { category, filters } = req.body;
const products = await Product.find({
category,
filters: {
$in: filters,
},
});
res.status(200).json(products);
} catch (err) {
res.status(500).json(err);
}
},
what stored on db
{
"_id" : ObjectId("62643acf19636d7db1804cb3"),
"images" : [
"image-1650735823476۸.jpg"
],
"user" : ObjectId("622606af0f40cb8ea37383dc"),
"name" : "شیر توپی 2 اینچ کلاس 150 پیشگام",
"description" : " برند پیشگام با مدارک و تاییدیه ",
"price" : NumberInt(5000000),
"category" : ObjectId("62445c4d922d127512867246"),
"filters" : [
{
"_id" : ObjectId("62643acf19636d7db1804cb4"),
"parent" : ObjectId("6264307f19636d7db1804b77"),
"value" : "626430bb19636d7db1804b78",
"name" : "Valve Type"
},
{
"_id" : ObjectId("62643acf19636d7db1804cb5"),
"parent" : ObjectId("6264319819636d7db1804b7b"),
"value" : "6264319819636d7db1804b7e",
"name" : "Body Type"
},
{
"_id" : ObjectId("62643acf19636d7db1804cb6"),
"parent" : ObjectId("626431ef19636d7db1804b82"),
"value" : "626431ef19636d7db1804b83",
"name" : "Bore Type"
},
{
"_id" : ObjectId("62643acf19636d7db1804cb7"),
"parent" : ObjectId("6264328519636d7db1804b85"),
"value" : "6264328519636d7db1804b86",
"name" : "Material Type"
},
{
"_id" : ObjectId("62643acf19636d7db1804cb8"),
"parent" : ObjectId("626435de19636d7db1804c10"),
"value" : "626439b619636d7db1804ca7",
"name" : "Trim Material"
},
{
"_id" : ObjectId("62643acf19636d7db1804cb9"),
"parent" : ObjectId("6264367919636d7db1804c17"),
"value" : "6264367919636d7db1804c18",
"name" : "End Conection"
},
{
"_id" : ObjectId("62643acf19636d7db1804cba"),
"parent" : ObjectId("626436a719636d7db1804c1f"),
"value" : "6264378119636d7db1804c28",
"name" : "Size"
},
{
"_id" : ObjectId("62643acf19636d7db1804cbb"),
"parent" : ObjectId("6264389219636d7db1804c6d"),
"value" : "6264389219636d7db1804c6f",
"name" : "Class / Pressure"
}
],
"subFilter" : [
{
"_id" : ObjectId("62643acf19636d7db1804cbc"),
"parent" : "6264328519636d7db1804b85",
"value" : "626433b919636d7db1804b93",
"title" : "Body Material"
}
],
"createdAt" : ISODate("2022-04-23T17:43:43.421+0000"),
"updatedAt" : ISODate("2022-04-23T17:53:29.016+0000"),
"__v" : NumberInt(0)
}
Consider this shrunk down set of inputs that capture the essence of the question. The comments "give away" what we are going to try to find and why. We only show one value for category because matching on that is trivial and not the interesting part of the query.
[
{
"category" : ObjectId("62445c4d922d127512867246"),
"filters" : [
// Matching Valve/value; include this doc
{"name" : "Valve", "value" : "626430bb19636d7db1804b78"},
// ALSO match Body/value; include this doc (but needs only 1 match)
{"name" : "Body", "value" : "6264319819636d7db1804b7e"}
]
}
,{
"category" : ObjectId("62445c4d922d127512867246"),
"filters" : [
// Not target value for Valve name (..79 instead of ...78):
{"name" : "Valve", "value" : "626430bb19636d7db1804b79"},
// ...but correct value for Body, so include this doc
{"name" : "Body", "value" : "6264319819636d7db1804b7e"}
]
}
,{
"category" : ObjectId("62445c4d922d127512867246"),
// No matching Valve or Body so this whole doc is ignored.
"filters" : [
{"name" : "Valve", "value" : "626430bb19636d7db1804b79"},
{"name" : "Body", "value" : "6264319819636d7db1804b7f"}
]
}
,{
"category" : ObjectId("62445c4d922d127512867246"),
// Not even name matches so ignore this too:
"filters" : [
{"name" : "Pipe", "value" : "6264319819636d7db1804eee"}
]
}
]
Assume also we set up inputs coming from the API like this, in their native form i.e. strings NOT ObjectId:
var targ_cat = '62445c4d922d127512867246';
var any_one_of = [
{ name: 'Valve', value: '626430bb19636d7db1804b78' },
{ name: 'Body', value: '6264319819636d7db1804b7e'}
];
We will use $filter as our main function but to do so, we must convert the incoming material into a form required by $filter.
// Convert inbound array of any_one_of into a something designed to work
// in the $filter function by comparing each name/value entry in the
// filters field to the item presented in $$this, meaning take:
// { name: 'Valve', value: '626430bb19636d7db1804b78' },
// and turn it into:
// {$and: [ {$eq:['Valve','$$this.name']}, {$eq:['62643...','$$this.value']} ] }
// Since any one of the entries is considered a hit, we package it all
// into an $or wrapper, not $and.
var or_list = [];
any_one_of.forEach(function(f) {
or_list.push( {$and: [
{$eq:[f['name'], '$$this.name']},
{$eq:[f['value'], '$$this.value']}
]});
});
var or_expr = {$or: or_list};
Now we are ready to query mongoDB:
db.foo.aggregate([
// Get this out of the way quickly; note we must make a new ObjectId!
{$match: {'category': new ObjectId(targ_cat)}}
// The interesting part of the query:
,{$addFields: {filters: {$filter: {input: '$filters', cond: or_expr}}}}
// Only keep those items where $filter found at least one of the
// targets:
,{$match: {$expr: {$gt:[{$size: '$filters'},0]} }}
]);

Mongoose aggregate query working as a mongodb query but not able to convert to mongoose

Below is my JSON structure
[{
"_id" : ObjectId("626204345ae3d8ec53ef41ee"),
"categoryName" : "Test Cate",
"__v" : 0,
"createdAt" : ISODate("2022-04-22T01:26:11.627Z"),
"items" : [
{
"itemName" : "Cate",
"user" : ObjectId("6260729af547915d9d876c23"),
"itemDescription" : "slkkndanslk",
"itemImage" : "/images/camping-table.jpeg",
"_id" : ObjectId("626204339b24b2ead6c05a70"),
"updatedAt" : ISODate("2022-04-22T01:26:11.627Z"),
"createdAt" : ISODate("2022-04-22T01:26:11.627Z")
}
],
"updatedAt" : ISODate("2022-04-22T01:26:11.627Z")
},
{
"_id" : ObjectId("62620e725ae3d8ec53ef4aa8"),
"categoryName" : "sdsad",
"__v" : 0,
"createdAt" : ISODate("2022-04-22T02:09:54.028Z"),
"items" : [
{
"itemName" : "asdada",
"user" : ObjectId("62620e6299145edb95147482"),
"itemDescription" : "asdsadad",
"itemImage" : "/images/camping-table.jpeg",
"_id" : ObjectId("62620e7299145edb95147486"),
"updatedAt" : ISODate("2022-04-22T02:09:54.028Z"),
"createdAt" : ISODate("2022-04-22T02:09:54.028Z")
},
{
"itemName" : "dsdsa",
"user" : ObjectId("62620e6299145edb95147482"),
"itemDescription" : "adasdad",
"itemImage" : "/images/camping-table.jpeg",
"_id" : ObjectId("62621b9c3662e0b4acabb71f"),
"updatedAt" : ISODate("2022-04-22T03:06:04.727Z"),
"createdAt" : ISODate("2022-04-22T03:06:04.727Z")
}
],
"updatedAt" : ISODate("2022-04-22T03:06:04.727Z")
}]
This is just one document and there would be array of documents. Also there may be multiple items within the same category.
I want to fetch all the items in all category with a particular userid. In MongoDB below is my query which is giving correct output on mongo shell
db.trades.aggregate([
{
$unwind: "$items"
},
{
$match: {
"items.user": ObjectId("6260729af547915d9d876c23")
}
}
]).pretty()
In mongoose I am doing the following thing but not getting the result
tradeModel.aggregate([ { $unwind : "$items" }, { $match : { "items.user" : id } } ])
.then(res => {
console.log(JSON.stringify(res))
})
Let me know what I am missing
Your parameter id is type string but mongodb store type ObjectId
change
tradeModel.aggregate([ { $unwind : "$items" }, { $match : { "items.user" : id } } ])
.then(res => {
console.log(JSON.stringify(res))
})
into
tradeModel.aggregate([ { $unwind : "$items" }, { $match : { "items.user" : {"$oid": id} } } ])
.then(res => {
console.log(JSON.stringify(res))
})
Got the answer we can use ObjectId(id) in search like this
tradeModel.aggregate([ { $unwind : "$items" }, { $match : { "items.user" : ObjectId(id) } } ])
.then(res => {
console.log(JSON.stringify(res))
})

Re-structure the data of the MongoDB $lookup Query.

I want this to be the result
help me, thank you
{
"_id" : ObjectId("5b74f57d3eb9591fcc069406"),
"received_by" : ObjectId("5b6bac617e9f754ff8aebd65"),
"received_date" : "2019",
"code" : "TRSV16081800007",
"items" : [
{
"m_souvenir_id" : ObjectId("5b70e98ccb72df3bec00c94a"),
"qty" : "10"
},
{
"m_souvenir_id" : ObjectId("5b70e98ccb72df3bec00c94a"),
"qty" : "10"
},
]
}
the result is like this
{
"_id" : ObjectId("5b74f57d3eb9591fcc069406"),
"received_by" : ObjectId("5b6bac617e9f754ff8aebd65"),
"received_date" : "2019",
"code" : "TRSV16081800007",
"items" : [
{
"m_souvenir_id" : ObjectId("5b70e98ccb72df3bec00c94a"),
"qty" : "10"
}
]
}
/* 2 */
{
"_id" : ObjectId("5b74f57d3eb9591fcc069406"),
"received_by" : ObjectId("5b6bac617e9f754ff8aebd65"),
"received_date" : "2019",
"code" : "TRSV16081800007",
"items" : [
{
"m_souvenir_id" : ObjectId("5b70e9d7cb72df3bec00c94b"),
"qty" : "20"
}
]
}
I have a project with nosql in mongodb
I have a problem with nosql in mongodb, I've tried searching in various sources, but the results are still not what I wantI have a project like this in mongodb,
db.t_souvenir.aggregate([
{ $lookup: { from: "t_souvenir_item", localField:"_id", foreignField:"t_souvenir_id", as: "Items"}},
{ $unwind : "$Items" },
{ $project : {
"code":1,
"received_by":1,
"received_date":1,
items : {
"m_souvenir_id":"$Items.m_souvenir_id",
"qty":"$Items.qty",
},
}};**strong text**
]);

How select data with given condition

I have following data.
{
"name" : "Maria",
"facebook" : [
{
"data" : "fb.com",
"privacy" : true
}
],
"twitter" : [
{
"data" : "twitter.com",
"privacy" : false
}
],
"google" : [
{
"data" : "google.com",
"privacy" : true
}
],
"phno" : [
{
"data" : "+1-1289741824124",
"privacy" : true
}
]
}
I want to return only data having privacy is equal to true. How do I do it ?
I tried but it returns all data having privacy is equal to false also. How do I query the data ?
Please post MongoDB query not Javascript code.
Thanks!
edit
having structure like this:
{
"_id" : ObjectId("575e4c8731dcfb59af388e1d"),
"name" : "Maria",
"providers" : [
{
"type" : "facebook",
"data" : "fb.com",
"privacy" : true
},
{
"type" : "twitter",
"data" : "twitter.com",
"privacy" : false
},
{
"type" : "google",
"data" : "google.com",
"privacy" : true
},
{
"type" : "phno",
"data" : "+1-1289741824124",
"privacy" : true
}
]
}
with query like this:
db.maria.aggregate([{
$project : {
_id : 1,
name : 1,
"providers" : {
$filter : {
input : "$providers",
as : "p",
cond : {
$eq : ["$$p.privacy", true]
}
}
}
}
}
])
])
we are gaining dynamic output, and we don't need to take care about provider name as this is covered by generic structure
{
"providers" : [
{
"type" : "facebook",
"data" : "fb.com",
"privacy" : true
},
{
"type" : "google",
"data" : "google.com",
"privacy" : true
},
{
"type" : "phno",
"data" : "+1-1289741824124",
"privacy" : true
}
],
"name" : "Maria"
}
end of edit
The way you could get this is using aggregation framework.
As we have an array for each field, we need to unwind it first, then we can use $project to set field value or simply null. As this looks like a simple query, it could give a bit of trouble. The way we can improve that is change a document structure, to have an array of providers and simple providerType field.
Aggregation stages below:
db.maria.find()
var unwindFb = {
$unwind : "$facebook"
}
var unwindtw = {
$unwind : "$twitter"
}
var unwindgo = {
$unwind : "$google"
}
var unwindph = {
$unwind : "$phno"
}
var project = {
$project : {
_id : 1,
name : 1, // list other fields here
facebook : {
$cond : {
if : {
$gte : ["$facebook.privacy", true]
},
then : [{
data : "$facebook.data",
privacy : "$facebook.privacy"
}
],
else : null
}
},
twitter : {
$cond : {
if : {
$gte : ["$twitter.privacy", true]
},
then : [{
data : "$twitter.data",
privacy : "$twitter.privacy"
}
],
else : null
}
},
google : {
$cond : {
if : {
$gte : ["$google.privacy", true]
},
then : [{
data : "$google.data",
privacy : "$google.privacy"
}
],
else : null
}
},
phno : {
$cond : {
if : {
$gte : ["$phno.privacy", true]
},
then : [{
data : "$phno.data",
privacy : "$phno.privacy"
}
],
else : null
}
}
}
}
db.maria.aggregate([unwindFb, unwindtw, unwindgo, unwindph, project])
then output looks like this:
{
"_id" : ObjectId("575df49d31dcfb59af388e1a"),
"name" : "Maria",
"facebook" : [
{
"data" : "fb.com",
"privacy" : true
}
],
"twitter" : null,
"google" : [
{
"data" : "google.com",
"privacy" : true
}
],
"phno" : [
{
"data" : "+1-1289741824124",
"privacy" : true
}
]
}
you can use the below code to iterate the object and check for the privacy true
var list = {
"name" : "Maria",
"facebook" : [
{
"data" : "fb.com",
"privacy" : true
}
],
"twitter" : [
{
"data" : "twitter.com",
"privacy" : false
}
],
"google" : [
{
"data" : "google.com",
"privacy" : true
}
],
"phno" : [
{
"data" : "+1-1289741824124",
"privacy" : true
}
]
}
$.each(Object.keys(list), function(index,value){
if(list[value][0].privacy)
{
console.log(list[value][0]);
}
});
If you are open to use lodash ...this is how you can do it...
var tmp = {
...you json here
}
var res =[];//result array of filtered data
_.forIn(tmp, function (o) {
if (Array.isArray(o)) {
if (o[0].privacy === true) {
res.push(o);
}
}
});

MONGO & Node.js: How to get an object within an array?

I just wonder how I can get an object within an array of objects. I just need that object.
This is the collection:
{
"net" : "192.168.1.1/24",
"_id" : ObjectId("531d1c2d857831021c48e3af"),
"ips" : [
{
"ips" : "192.168.1.1",
"_id" : ObjectId("531d1c2d857831021c48e3b3")
},
{
"ips" : "192.168.1.33",
"_id" : ObjectId("531d1c2d857831021c48e3b2")
},
{
"ips" : "192.168.1.38",
"_id" : ObjectId("531d1c2d857831021c48e3b1")
},
{
"ips" : "192.168.1.106",
"_id" : ObjectId("531d1c2d857831021c48e3b0")
}
],
"__v" : 0
}
I need the object with "531d1c2d857831021c48e3b0" ID, what is the sentence to get only that object? I tried with db.nets.find({ "ips._id": ObjectId("531d1c2d857831021c48e3b3") } ) but I get the whole collection.
Thank you very much.
Edit. With the code I receive this:
db.nets.find(
{
"_id": ObjectId("531d1c2d857831021c48e3af"),
"ips._id": ObjectId("531d1c2d857831021c48e3b3")
},
{ "ips.$" : 1 }
)
{
"_id" : ObjectId("531d1c2d857831021c48e3af"),
"ips" : [
{},
{},
{},
{}
]
}
but what I want to receive is this:
{
"ips" : "192.168.1.33",
"_id" : ObjectId("531d1c2d857831021c48e3b2")
}
Use projection. The positional $ operator allows you to just select the matching index of the array.
db.nets.find(
{
"_id": ObjectId("531d1c2d857831021c48e3af"),
"ips._id": ObjectId("531d1c2d857831021c48e3b3")
},
{ "ips.$" : 1 }
)
Which gives this response:
{
"_id" : ObjectId("531d1c2d857831021c48e3af"),
"ips" : [
{
"ips" : "192.168.1.1",
"_id" : ObjectId("531d1c2d857831021c48e3b3")
}
]
}
It's not the "whole collection", it's the "whole document", in which unless you filter the fields with a "projection" you will get by default.

Categories