MongoDB Aggregate count based on multiple collections - mongodb

How to get tag (from iptag) total based on host (from services) total ? Ex: If a host match tagAAA filter condition, total += 1.
hostmin <= ip2int(host) <= hostmax
collection services:
db.getCollection('services').insert({"host" : "172.21.4.205", "port" : 80, "service" : "http"})
db.getCollection('services').insert({"host" : "172.21.4.97", "port" : 445, "service" : "smb"})
collection iptag:
db.getCollection('iptag').insert({
"tag" : [
"tagAAA"
],
"hostmin" : 2886991873.0,
"hostmax" : 2887057406.0,
"cidr" : "172.20.0.0/16"
}
db.getCollection('iptag').insert({
"tag" : [
"tagBBB"
],
"hostmin" : 2887057409.0,
"hostmax" : 2887122942.0,
"cidr" : "172.21.0.0/16"
}

Related

SpringBoot MongoDB: how to find the CLOSEST POSITIVE DIFF document?

Considering a collection with the following documents:
[{
"_id" : ObjectId("5f984d04093a1a0be1237db2"),
"postalCode" : "",
"latitude" : -33.4939994812012,
"longitude" : 143.210403442383,
"accuracyRadius" : 1000,
"network" : "1.0.0.0/24",
"geoNameID" : 2077456,
"registeredCountryGeoNameID" : 2077456,
"anonymousProxy" : false,
"satelliteProvider" : false,
"_class" : "project.domain.maxmind.block.GeoLite2CityBlockIPv4"
},
{
"_id" : ObjectId("5f984d04093a1a0be1237db3"),
"postalCode" : "",
"latitude" : 34.7724990844727,
"longitude" : 113.726600646973,
"accuracyRadius" : 50,
"network" : "1.0.1.0/24",
"geoNameID" : 1814991,
"registeredCountryGeoNameID" : 1814991,
"anonymousProxy" : false,
"satelliteProvider" : false,
"_class" : "project.domain.maxmind.block.GeoLite2CityBlockIPv4"
},
{
"_id" : ObjectId("5f984d04093a1a0be1237db4"),
"postalCode" : "",
"latitude" : 34.7724990844727,
"longitude" : 113.726600646973,
"accuracyRadius" : 50,
"network" : "1.0.2.0/23",
"geoNameID" : 1814991,
"registeredCountryGeoNameID" : 1814991,
"anonymousProxy" : false,
"satelliteProvider" : false,
"_class" : "project.domain.maxmind.block.GeoLite2CityBlockIPv4"
}]
How can I write an efficient query for the closest network, starting from an IP address (string) as the input?
E.g. considering the network 1.0.1.0/24
and the IPv4 1.0.1.200
I should convert the IPv4 to its corresponding integer value
1.0.1.200 --> 16777672
and do the same for each network
network 1.0.0.0/24 --> 16777216
host min 1.0.0.1 --> 16777217
host max 1.0.0.254 --> 16777470
network 1.0.1.0/24 --> 16777472
host min 1.0.1.1 --> 16777473
host max 1.0.1.254 --> 16777726
network 1.0.2.0/23 --> 16777728
host min 1.0.2.1 --> 16777729
host max 1.0.3.254 --> 16778238
Then I would need to do a diff among the IP and the network to find the closest positive one:
16777672 - 16777216 = 456
16777672 - 16777472 = 200
16777672 - 16777728 = -56
How could I write such a query, considering that both the IPs and networks are Strings?
I could do just the conversion of the IP to its integer value, before passing it to the #Repository, but then I would need to convert the network addresses inside the #Query.
#Repository
public interface GeoLite2CityBlockIPv4Repository extends ReactiveMongoRepository<GeoLite2CityBlockIPv4, BigInteger>, ReactiveQuerydslPredicateExecutor<GeoLite2CityBlockIPv4> {
Mono<GeoLite2CityBlockIPv4> findOneByNetwork(String network);
#Query("{?}")
Mono<GeoLite2CityBlockIPv4> findOneByIP(Integer ip);
}

And Operator in Criteria not working as expected for nested documents inside aggregation Spring Data Mongo

I am trying to fetch total replies where read values for a replies is true. But I am getting count value as 3 but expected value is 2 (since only two read value is true) through Aggregation function available in Spring Data Mongo. Below is the code which I wrote:
Aggregation sumOfRepliesAgg = newAggregation(match(new Criteria().andOperator(Criteria.where("replies.repliedUserId").is(userProfileId),Criteria.where("replies.read").is(true))),
unwind("replies"), group("replies").count().as("repliesCount"),project("repliesCount"));
AggregationResults<Comments> totalRepliesCount = mongoOps.aggregate(sumOfRepliesAgg, "COMMENTS",Comments.class);
return totalRepliesCount.getMappedResults().size();
Using AND Operator inside Criteria Query and passed two criteria condition but not working as expected. Below is the sample data set:
{
"_id" : ObjectId("5c4ca7c94807e220ac5f7ec2"),
"_class" : "com.forum.api.domain.Comments",
"comment_data" : "logged by karthe99",
"totalReplies" : 2,
"replies" : [
{
"_id" : "b33a429f-b201-449b-962b-d589b7979cf0",
"content" : "dasdsa",
"createdDate" : ISODate("2019-01-26T18:33:10.674Z"),
"repliedToUser" : "#karthe99",
"repliedUserId" : "5bbc305950a1051dac1b1c96",
"read" : false
},
{
"_id" : "b886f8da-2643-4eca-9d8a-53f90777f492",
"content" : "dasda",
"createdDate" : ISODate("2019-01-26T18:33:15.461Z"),
"repliedToUser" : "#karthe50",
"repliedUserId" : "5c4bd8914807e208b8a4212b",
"read" : true
},
{
"_id" : "b56hy4rt-2343-8tgr-988a-c4f90598h492",
"content" : "dasda",
"createdDate" : ISODate("2019-01-26T18:33:15.461Z"),
"repliedToUser" : "#karthe50",
"repliedUserId" : "5c4bd8914807e208b8a4212b",
"read" : true
}
],
"last_modified_by" : "karthe99",
"last_modified_date" : ISODate("2019-01-26T18:32:41.394Z")
}
What is the mistake in the query that I wrote?

Mongo greater than comparison returns 0

I am trying to count all car dealers who's total fleet units is over 1000. This is the code I wrote to do it, however, it returns 0 and I know for a fact there are quite a few records in this data set that are over 1000.
db.Car_Dealership.find({Totalfleetunits : {$gte: 1000} }).count()
This is a sample of what's in my database, both records have total fleets over 1000. Any ideas why it returns 0?
"_id" : ObjectId("5a203ab0b9574375830354d4"),
"2016rank" : 6,
"Dealershipgroupname" : "Hendrick Automotive Group",
"Address" : "6000 Monroe Road",
"City/State/Zip" : "Charlotte, NC 28212",
"Phone" : "(704) 568-5550",
"Companywebsite" : "www.hendrickauto.com",
"Topexecutive" : "Rick Hendrick",
"Topexecutivetitle" : "chairman",
"Totalnewretailunits" : "117,946",
"Totalusedunits" : "88,458",
"Totalfleetunits" : "4,646",
"Totalwholesaleunits" : "56,569",
"Total_units" : "267,619",
"Total_number_of _dealerships" : 103,
"Grouprevenuealldepartments*" : "$8,551,253,132",
"2015rank" : 6
}
{
"_id" : ObjectId("5a203ab0b9574375830354d5"),
"2016rank" : 5,
"Dealershipgroupname" : "Sonic Automotive Inc.?",
"Address" : "4401 Colwick Road",
"City/State/Zip" : "Charlotte, NC 28211",
"Phone" : "(704) 566-2400",
"Companywebsite" : "www.sonicautomotive.com",
"Topexecutive" : "B. Scott Smith",
"Topexecutivetitle" : "CEO",
"Totalnewretailunits" : "134,288",
"Totalusedunits" : "119,174",
"Totalfleetunits" : "1,715",
"Totalwholesaleunits" : "35,098",
"Total_units" : "290,275",
"Total_number_of _dealerships" : 112,
"Grouprevenuealldepartments*" : "$9,731,778,000",
"2015rank" : 4
That happens because the value of Totalfleetunits is stringType.
Now to solve your problem you have to options.
option 1:
You can change your schema for Totalfleetunits to the type of Number and change all the documents Totalfleetvalues value from string to a number. Like,
"Totalfleetunits": "4,646" needs to be changed with "Totalfleetunits"
: "4646"
option 2:
You can use javascript in your query to first remove , from your value then check the Totalfleetunits value for greater than or equal to ( >= ). Only need to change a single line of code as I given below.
db.Car_Dealership.find("this.Totalfleetunits.replace(',','') >= 1000").count()

Mongodb put Documents array as the same level

I have this array of documents, I would like to put "table" on the same level like mastil_antenas and other variables. how Can I do that with aggregate?
I'm trying with the aggregate $project but I can't get the result.
Example of Data
[ {
"mastil_antena" : "1",
"nro_platf" : "1",
"antmarcmast" : "ANDREW",
"antmodelmast" : "HWXXX6516DSA3M",
"retmarcmast" : "Ericsson",
"retmodelmast" : "ATM200-A20",
"distmast" : "1.50",
"altncramast" : "41.30",
"ORIENTMAG" : "73.00",
"incelecmast" : "RET",
"incmecmast" : "1.00",
"Feedertypemast" : "Fibra Optica",
"longjumpmast" : "5.00",
"longfo" : "100",
"calibrecablefuerza" : "10 mm",
"longcablefuerza" : "65.00",
"modelorruantena" : "32B66A",
"tiltmecfoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114934746000.jpg",
"tiltmecfoto_fh" : "2017-10-18T05:51:22Z",
"az0foto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017115012727000.jpg",
"az0foto_fh" : "2017-10-18T05:55:21Z",
"azneg60foto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017115016199000.jpg",
"azneg60foto_fh" : "2017-10-18T05:55:36Z",
"azpos60foto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017115020147000.jpg",
"azpos60foto_fh" : "2017-10-18T05:55:49Z",
"etiqantenafoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114920853000.jpg",
"etiqantenafoto_fh" : "2017-10-18T05:56:01Z",
"tiltelectfoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114914236000.jpg",
"tiltelectfoto_fh" : "2017-10-18T05:56:13Z",
"idcablefoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114900279000.jpg",
"idcablefoto_fh" : "2017-10-18T05:56:38Z",
"rrutmafoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114947279000.jpg",
"rrutmafoto_fh" : "2017-10-18T05:56:49Z",
"etiquetarrufoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114954648000.jpg",
"etiquetarrufoto_fh" : "2017-10-18T05:57:02Z",
"rrutmafoto1" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114959738000.jpg",
"rrutmafoto1_fh" : "2017-10-18T05:57:12Z",
"etiquetarrufoto1" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017115005545000.jpg",
"etiquetarrufoto1_fh" : "2017-10-18T05:57:27Z",
"botontorre4" : "sstelcel3",
"table" : { /* put all varibles one level up*/
"tecmast" : "LTE",
"frecmast" : "2100",
"secmast" : "1",
"untitled440" : "Salir"
},
"comentmast" : "",
"longfeedmast" : "",
"numtmasmast" : "",
"otra_marca_antena" : "",
"otro_modelo_antena" : ""
}]
Starting from MongoDB version 3.4 you could use $addFields to do this.
//replace products with what makes sense in your database
db.getCollection('products').aggregate(
[
{ //1 add the properties from subdocument table to documents
$addFields: {
"documents.tecmast" : "documents.0.table.tecmast",
"documents.frecmast" : "documents.0.table.frecmast",
"documents.secmast" : "documents.0.table.secmast",
"documents.untitled440" : "documents.0.table.untitled440"
}
},
{
//(optional) 2 remove the table property from the documents
$project: {"documents.table" : 0}
}
]
)
Step 1: use $addFields to grab properties from table inside documents.table and put them on documents
Step 2: (optional) remove property "table" from documents.
I hope this helps!!!

How to find something from an array in mongo

{
"_id" : ObjectId("586aac4c8231ee0b98458045"),
"store_code" : NumberInt(10800),
"counter_name" : "R.N.Electric",
"address" : "314 khatipura road",
"locality" : "Khatipura Road (Jhotwara)",
"pincode" : NumberInt(302012),
"town" : "JAIPUR",
"gtm_city" : "JAIPUR",
"sales_office" : "URAJ",
"owner_name" : "Rajeev",
"owner_mobile" : "9828024073",
"division_mapping" : [//this contains only 1 element in every doc
{
"dvcode" : "cfc",
"dc" : "trade",
"beatcode" : "govindpura",
"fos" : {
"_id" : ObjectId("586ab8318231ee0b98458843"),
"loginid" : "9928483483",
"name" : "Arpit Gupta",
"division" : [
"cfc",
"iron"
],
"sales_office" : "URAJ", //office
"gtm_city" : "JAIPUR" //city
},
"beat" : {
"_id" : ObjectId("586d372b39f64316b9c3cbd7"),
"division" : {
"_id" : ObjectId("5869f8b639f6430fe4edee2a"),
"clientdvcode" : NumberInt(40),
"code" : "cfc",
"name" : "Cooking & Fabric Care",
"project_code" : "usha-fos",
"client_code" : "usha",
"agent_code" : "v5global"
},
"beatcode" : "govindpura",
"sales_office" : "URAJ",
"gtm_city" : "JAIPUR",
"active" : true,
"agency_code" : "v5global",
"client_code" : "USHA_FOS",
"proj_code" : "usha-fos",
"fos" : {
"_id" : ObjectId("586ab8318231ee0b98458843"),
"loginid" : "9928483483",
"name" : "Arpit Gupta",
"division" : [
"cfc",
"iron"
],
"sales_office" : "URAJ",
"gtm_city" : "JAIPUR"
}
}
}
],
"distributor_mail" : "sunil.todi#yahoo.in",
"project_code" : "usha-fos",
"client_code" : "usha",
"agent_code" : "v5global",
"distributor_name" : "Sundeep Electrical"
}
I am having only 1 element in division_mapping's array and I want to find those documents whose dc in division_mapping is trade.
I have tried following:
"division_mapping":{$elemMatch:{$eq:{"dc":"trade"}}}})
Dont know what I am doing wrong.
//Maybe I have to unwind the array but is there any other way?
According to MongoDB documentation
The $elemMatch operator matches documents that contain an array
field with at least one element that matches all the specified query
criteria.
According to above mentioned description to retrieve only documents whose dc in division_mapping is trade please try executing below mentioned query
db.collection.find({division_mapping:{$elemMatch:{dc:'trade'}}})