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

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**
]);

Related

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))
})

Elastic Search delete a single element inside a field on _source

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
}
}

MongoDB .find() only ObjectId's embedded in an Array.

I am trying to get only the ObjectId's from One specific Document that is embedded in the projects Array.
Basically I am trying to make a database that will have users and each user will have there own projects.
Thank you !
db.users.find().pretty()
{
"_id" : ObjectId("5762c0cf2b9a78006373a684"),
"name" : "seq",
"pass" : "seq",
"projects" : [
{
"pid" : ObjectId("5762c0ba2b9a78006373a682"),
"name" : "aaa"
},
{
"pid" : ObjectId("5762c0ba2b9a78006373a683"),
"name" : "bbb"
}
]
}
{
"_id" : ObjectId("5762c28d2b9a78006373a687"),
"name" : "leq",
"pass" : "leq",
"projects" : [
{
"pid" : ObjectId("5762c2892b9a78006373a685"),
"name" : "ccc"
},
{
"pid" : ObjectId("5762c2892b9a78006373a686"),
"name" : "ddd"
}
]
}
let say we want two pids
{"pid" : ObjectId("5762c0ba2b9a78006373a682")} and
{"pid" : ObjectId("5762c2892b9a78006373a686"),}
and only inner documents
so required response should look like:
{
"_id" : ObjectId("5762c0ba2b9a78006373a682"),
"name" : "aaa"
},{
"_id" : ObjectId("5762c2892b9a78006373a686"),
"name" : "ddd"
}
Aggregation framework can manipulate documents, match only needed ones and transform inner structure by project phase:
var match = {
$match : {
"projects.pid" : {
$in : [ObjectId("5762c0ba2b9a78006373a682"),
ObjectId("5762c2892b9a78006373a686")]
}
}
}
var unwind = {
$unwind : "$projects"
};
// now move array objet as top level object
var project = {
$project : {
_id : "$projects.pid",
name : "$projects.name",
// list other fields here
}
}
db.vic.aggregate([match, unwind, match, project])

Meteor Mongodb count fields in nested object

I am trying to create a dashboard where I show summaries of order data within the app. In this case I am simply wanting count the number of items in a given category in my Orders collection. My code so far looks like this:
Collection data
{
"_id" : "a6wHiXxyM5DwSAsfq",
"orderNumber" : 1234,
"createdAt" : "11/01/2016, 14:43:49",
"productsInOrder" : [
{
"category" : "ambient",
"item" : 50818,
"desc" : "Tasty Rubber Chicken",
"quantity" : "44",
"price" : "0.92",
"lineprice" : "40.48",
"_id" : "FFNxG8vujs6NGN69r"
},
{
"category" : "frozen",
"item" : 71390,
"desc" : "Generic Granite Fish",
"quantity" : "11",
"price" : "1.00",
"lineprice" : "11.00",
"_id" : "LcRtpyLxkWyh39kkB"
}
]
}
{
"_id" : "PdpywXCvfew7qojmA",
"orderNumber" : 1234,
"createdAt" : "11/01/2016, 14:44:15",
"productsInOrder" : [
{
"category" : "frozen",
"item" : 71390,
"desc" : "Generic Granite Fish",
"quantity" : "44",
"price" : "1.00",
"lineprice" : "44.00",
"_id" : "dAscx4R8pcBgbzoZs"
},
{
"category" : "frozen",
"item" : 66940,
"desc" : "Gorgeous Granite Bike",
"quantity" : "55",
"price" : "4.21",
"lineprice" : "231.55",
"_id" : "xm3mFRmPmmdPxjfP9"
},
{
"category" : "frozen",
"item" : 96029,
"desc" : "Gorgeous Plastic Fish",
"quantity" : "1234",
"price" : "4.39",
"lineprice" : "5417.26",
"_id" : "7u7SHnpTf7PWcrhGA"
}
]
}
{
"_id" : "xcHZ25qwvyDpDJtAZ",
"orderNumber" : 1234,
"createdAt" : "11/01/2016, 14:44:47",
"productsInOrder" : [
{
"category" : "frozen",
"item" : 31104,
"desc" : "Handcrafted Rubber Keyboard",
"quantity" : "11",
"price" : "4.78",
"lineprice" : "52.58",
"_id" : "LMMwbKFEgnCbgCt9c"
},
{
"category" : "frozen",
"item" : 77832,
"desc" : "Practical Rubber Shirt",
"quantity" : "21",
"price" : "0.62",
"lineprice" : "13.02",
"_id" : "63otkkXWGrTJkwEgX"
},
{
"category" : "frozen",
"item" : 66940,
"desc" : "Gorgeous Granite Bike",
"quantity" : "111",
"price" : "4.21",
"lineprice" : "467.31",
"_id" : "rbPSujey8CFeMPjza"
}
]
}
JS
So far I have tried:
Orders.find({ 'productsInOrder': ['ambient']}).count();
Orders.find({ productsInOrder: { category: 'ambient' }}).count();
Orders.find({ productsInOrder: { $all: [ 'frozen' ] }}).count();
I am having a hard time understanding Mongo queries when the data is nested in this manner. Please can you help point me in the right direction? Many thanks in advance.
* SOLUTION *
I have accomplished the desired result thanks to the contributions below. To make this work I created a method on the server as the query cannot be run on the client using an existing collection. This is done as follows:
Meteor.methods({
'byCategory': function() {
var result = Orders.aggregate([
{ "$unwind": "$productsInOrder" },
{
"$group": {
"_id": null,
"ambient_count": {
"$sum": {
"$cond": [ { "$eq": [ "$productsInOrder.category", "ambient" ] }, 1, 0 ]
}
},
"frozen_count": {
"$sum": {
"$cond": [ { "$eq": [ "$productsInOrder.category", "frozen" ] }, 1, 0 ]
}
},
"other_category_count": {
"$sum": {
"$cond": [ { "$eq": [ "$productsInOrder.category", "other_category" ] }, 1, 0 ]
}
}
}
}
]);
return result;
}
})
and then on the client:
Meteor.call('byCategory', function( error, result ) {
if( error ) {
console.log( error.reason );
} else {
console.log( result[0].ambient_count );
console.log( result[0].frozen_count );
etc....
}
});
Thanks and credit to #chridam and #Brett.
An alternative approach is to use the aggregation framework. Consider the following aggregation pipeline which as the first stage of the aggregation pipeline, the $unwind operator denormalizes the productsInOrder array to output for each input document, n documents where n is the number of array elements. The next pipeline stage has the $group operator which groups all the documents into a single document and stores the counts for each category with the help of the $sum and $cond operators.
In Meteor, you can then use meteorhacks:aggregate package to implement the aggregation:
Add to your app with
meteor add meteorhacks:aggregate
Note, this only works on server side and there is no oberserving support or reactivity built in. Then simply use .aggregate function like below.
var coll = new Mongo.Collection('orders');
var pipeline = [
{ "$unwind": "$productsInOrder" },
{
"$group": {
"_id": null,
"ambient_count": {
"$sum": {
"$cond": [ { "$eq": [ "$productsInOrder.category", "ambient" ] }, 1, 0 ]
}
},
"frozen_count": {
"$sum": {
"$cond": [ { "$eq": [ "$productsInOrder.category", "frozen" ] }, 1, 0 ]
}
},
"other_category_count": {
"$sum": {
"$cond": [ { "$eq": [ "$productsInOrder.category", "other_category" ] }, 1, 0 ]
}
}
}
}
];
var result = coll.aggregate(pipeline);
Running the same pipeline in mongo shell using the sample data will yield:
{
"result" : [
{
"_id" : null,
"ambient_count" : 1,
"frozen_count" : 7,
"other_category_count" : 0
}
],
"ok" : 1
}
You can access the native mongo collection and publish the aggregation results to the orders collection on the client side:
Meteor.publish('categoryCounts', function() {
var self = this,
db = MongoInternals.defaultRemoteCollectionDriver().mongo.db;
orders = db.collection("orders").aggregate(pipeline, // Need to wrap the callback so it gets called in a Fiber.
Meteor.bindEnvironment(
function(err, result) {
// Add each of the results to the subscription.
_.each(result, function(e) {
self.added("orders", e._id, e);
});
self.ready();
},
function(error) {
Meteor._debug( "Error doing aggregation: " + error);
}
)
);
});
If you don't want to do this within Meteor, you will need to use mongo aggregation. Minimongo doesn't include aggregation though, so you will need this package to accomplish it:
https://docs.mongodb.org/manual/core/aggregation-introduction/
I only tested this in mongo itself, so you will have to adapt it to the way that the aggregation package does it:
db.orders.aggregate([
{
$unwind: "$productsInOrder"
},
{
$match: {
"productsInOrder.category": "frozen"
}
},
{
$group: {
_id: null,
count: {
$sum: 1
}
}
}
]);
The first part is unwinding the collection. It will basically make an "order" entry for every instance of $productsInOrder. Once you have the array flattened out, we match on the category you care about; in this case, the "frozen" category. Next we group it up so we can count the number of documents returned. $group is simply constructing the final object that will be output from the query. You can modify this to be whatever you want, or you could group by productsInOrder.category and not even $match on "frozen".

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