fuzzy search for mongodb Documents - mongodb

some mongo document is like that:
{
"_id" : "class1",
"member" : [
[
"Tom",
"1057004"
],
[
"Dean",
"1274858"
],
[
"Bob",
"1276155"
],
[
"Alice",
"1046496"
],
[
"Max",
"1276063"
]
],
"teacher" : "Jack",
"year" : "2014"
}
I want a Fuzzy Search for member's name, for example only search "al" result is this document.
I can use regex for normal search,how to use it in multiple List ?
thanks

Related

Return only matching sub document from MongoDB document

We have following structure in our Mongo collection
{
"_id" : ObjectId("5f98aeadbaf1ea001affe4c0"),
"name" : "Temp",
"campaigntype" : 3,
"startdate" : ISODate("2021-01-01T00:00:00.000Z"),
"enddate" : ISODate("2021-01-01T00:00:00.000Z"),
"affiliatetag" : "",
"promotedtitles" : [
{
"primaryisbn" : "9781453238431",
"promoprice" : "1.99",
"countries" : [
"US",
"CA",
"AU",
"GB"
],
"retailers" : [
"ALL"
],
"dlp" : "17.99",
"notes1" : "History",
"notes2" : "",
"sequence" : 1
},
{
"primaryisbn" : "9781504063562",
"promoprice" : "1.99",
"countries" : [
"US",
"CA"
],
"retailers" : [
"ALL"
],
"dlp" : "11.99",
"notes1" : "Thrillers",
"notes2" : "",
"sequence" : 2
},
{
"primaryisbn" : "9781497673984",
"promoprice" : "0.99",
"countries" : [
"US",
"CA"
],
"retailers" : [
"ALL"
],
"dlp" : "6.99",
"notes1" : "Romantic Suspense",
"notes2" : "",
"sequence" : 3
},
{
"primaryisbn" : "9780547526959",
"promoprice" : "1.99",
"countries" : [
"CA"
],
"retailers" : [
"All"
],
"dlp" : "17.99",
"notes1" : "History",
"notes2" : "",
"sequence" : 4
},
{
"primaryisbn" : "9781453274248",
"promoprice" : "1.99",
"countries" : [
"US"
],
"retailers" : [
"All"
],
"dlp" : "9.99",
"notes1" : "Historical Fiction",
"notes2" : "",
"sequence" : 5
}
],
"active" : true,
"createdby" : ObjectId("5d2e2755d3851f0012108a05")
}
We need to write a query by passing single country like ['US'] or multiple country like ['US', 'CA']. Query should only return us matching sub document from promoted titles.
For example, If we pass country as 'US', we should get primary isbn 9781453238431, 9781504063562, 9781497673984 and 9781453274248. If we pass country as ['GB', 'CA'], we need to get 9781453238431, 9781504063562, 9781497673984 and 9780547526959. If we pass ['GB'], we should only get 9781453238431 sub document
We were trying with promotedtitles.countries : {$in : ['US', 'CA']} but that don't work.
Thanks in advance
You can $unwind and $match like this:
$unwind is to deconstruct the array and get every object as a different value instead all together in an array.
Then you can filter each object using $match and $in.
db.collection.aggregate([
{
"$unwind": "$promotedtitles"
},
{
"$match": {
"promotedtitles.countries": {
"$in": [
"US"
]
}
}
},
{
"$project": {
"_id": 0,
"result": "$promotedtitles.primaryisbn"
}
}
])
Example here using US and here with GB, CA.
Also, if you want to get all ISBNs in an array you can add a $group like this example

How to convert existing array of string to custom object array in mongodb?

I have some existing data and I want to update it but I can't able to build a query for that.
I want to convert and update Options field which is string array to object array.
Is it possible or not?
I tried arrayToObject but it doesn't work
Below is my existing record:
{
"_id" : ObjectId("5b6455d9c006ae9d142b0da8"),
"PartnerId" : "585938e3d4e9dac9bb2b09c6",
"BusinessID" : NumberLong(98),
"Responses" : [
{
"QID" : 1,
"Order" : 1,
"Question" : "Contact Information 1",
"Options" : [
"First Name",
"Address",
"Email",
"Phone"
],
"Answers" : [
"First Name",
"111, Dublin, California, 94568",
"forms1#vagaro.com",
"111"
]
},
{
"QID" : 8,
"Order" : 6,
"Question" : "Contact Information 2",
"Options" : [
"Address",
"Email"
],
"Answers" : [
"5000 Estate Enighed, Independence, Kansas, 67301"
]
}
]
}
Expected result:
{
"_id" : ObjectId("5b6455d9c006ae9d142b0da8"),
"PartnerId" : "585938e3d4e9dac9bb2b09c6",
"BusinessID" : NumberLong(98),
"Responses" : [
{
"QID" : 1,
"Order" : 1,
"Question" : "Contact Information 1",
"Options" : [
{Option:"First Name", Order:1},
{Option:"Address", Order:2},
{Option:"Email", Order:3},
{Option:"Phone", Order:4}
],
"Answers" : [
"First Name",
"111, Dublin, California, 94568",
"forms1#vagaro.com",
"111"
]
},
{
"QID" : 8,
"Order" : 6,
"Question" : "Contact Information 2",
"Options" : [
{Option:"Address", Order:1},
{Option:"Email" , Order:2}
],
"Answers" : [
"5000 Estate Enighed, Independence, Kansas, 67301"
]
}
]
}
Please help me.
Thanks
You can use Aggregation like follows. I used mongo shell with the same document you described.
db.test.aggregate([
{ $match: {} },
{
$project: {
_id: "$_id",
PartnerId: "$PartnerId",
BusinessID: "$BusinessID",
Responses: {
$map: {
input: "$Responses",
as: 'response',
in: {
"QID" : "$$response.QID",
"Order" : "$$response.Order",
"Question" : "$$response.Question",
"Options" : {
$map: {
input: "$$response.Options",
as: 'option',
in: {
Option: "$$option",
Order: {
$sum: [
{
$indexOfArray: [
"$$response.Options",
"$$option"
]
},
1
]
}
}
}
},
"Answers" : "$$response.Answers"
}
}
}
}
},
{ $out: 'output' }
])
Will output the desired documents to the collection output. You can check it and rename it later or just specify another collection name in the $out stage if you want to override/create another collection.

MongoDB $geoIntersects doesn't return any data for particular city

I got coordinates manually from google maps for Chennai and Bangalore cities and inserted into my DB. For Bangalore city, $geoIntersect works perfectly. However, for some reason for Chennai city, it doesn't show up. Am not sure where/what am I missing. Attaching my code below
Bangalore City Details
{
"_id" : ObjectId("5b2d45ef4b511713052b49f9"),
"cityId" : 10256,
"countryEn" : "india",
"countryAr" : "india ar",
"provinceEn" : "Bangalore",
"provinceAr" : "Bangalore ar",
"cityEn" : "Bangalore",
"cityAr" : "Bangalore ar",
"lat" : 12.972442,
"lon" : 77.580643,
"countryCode" : "+91",
"population" : 150257,
"boundaries" : {
"coordinates" : [
[
[
77.747618,
13.105034
],
[
77.758604,
13.039487
],
[
77.816283,
12.959201
],
[
77.825896,
12.853452
],
[
77.742125,
12.884244
],
[
77.700926,
12.797213
],
[
77.461973,
12.783821
],
[
77.412535,
12.911017
],
[
77.390562,
13.047514
],
[
77.525145,
13.150506
],
[
77.636381,
13.155855
],
[
77.747618,
13.105034
]
]
],
"type" : "Polygon"
}
}
Query i used
db.Cities_Master.find({
boundaries: {
$geoIntersects: {
$geometry: { type: 'Point', coordinates: [77.5476, 13.105034] },
},
},
})
Chennai City Details
{
"_id" : ObjectId("5b2d4a734b511713052b4a01"),
"cityId" : 10255,
"countryEn" : "india",
"countryAr" : "india ar",
"provinceEn" : "chennai",
"provinceAr" : "chennai ar",
"cityEn" : "chennai",
"cityAr" : "chennai ar",
"lat" : 13.067439,
"lon" : 80.237617,
"countryCode" : "+91",
"population" : 150257,
"boundaries" : {
"coordinates" : [
[
[
80.309211,
13.257326
],
[
80.332557,
13.241285
],
[
80.332557,
13.249305
],
[
80.295478,
13.091519
],
[
80.248786,
12.838584
],
[
80.149909,
12.880089
],
[
80.097724,
12.936309
],
[
80.123816,
13.14368
],
[
80.320197,
13.199841
],
[
80.178748,
13.2092
],
[
80.239173,
13.215885
],
[
80.309211,
13.257326
]
]
],
"type" : "Polygon"
}
}
Query i used to find chennai
db.Cities_Master.find({
boundaries: {
$geoIntersects: {
$geometry: { type: 'Point', coordinates: [80.309211, 13.257326] },
},
},
})
For Chennai query, I get No records found. Have I inserted coordinates in the wrong manner or any other issue? Any help would be appreciated. Thanks
Bangalore City coordinates are represented by valid, closed polygon and that's why MongoDB query works. In Chennai case the order of coordinates is incorrect. You can easily check it here:
So to fix that you can reorder incorrect coordinates in the database. Valid document for Chennai could look like this:
db.Cities_Master.save({
"_id" : ObjectId("5b2d4a734b511713052b4a01"),
"cityId" : 10255,
"countryEn" : "india",
"countryAr" : "india ar",
"provinceEn" : "chennai",
"provinceAr" : "chennai ar",
"cityEn" : "chennai",
"cityAr" : "chennai ar",
"lat" : 13.067439,
"lon" : 80.237617,
"countryCode" : "+91",
"population" : 150257,
"boundaries" : {
"coordinates" : [
[
[
80.309211,
13.257326
],
[
80.332557,
13.249305
],
[
80.332557,
13.241285
],
[
80.320197,
13.199841
],
[
80.295478,
13.091519
],
[
80.248786,
12.838584
],
[
80.149909,
12.880089
],
[
80.097724,
12.936309
],
[
80.123816,
13.14368
],
[
80.178748,
13.2092
],
[
80.239173,
13.215885
],
[
80.309211,
13.257326
]
]
],
"type" : "Polygon"
}
})
Which can be previewed here. In that case your query works fine.

Combine different collection result into one in Mongo

Below is my query I want the result of shp_tx_survey_with_index and
for each loop collection shp_counties_with_index name1 and name2 together of both this collection. If running this query separate then getting the result but this query gives me nothing. I want result like Range_Township, Survey, Section, abstract, centroid, name_1, name_2.
db.shp_tx_survey_with_index.aggregate(
[
{ $match: { "centroid": { "$ne": null } } },
{ $limit: 5 },
{
$project: {
Range_Township: "$l1surnam",
Survey: "$l4surnam",
Section: "$l1surnam",
abstract: "$abstract_",
centroid: "$centroid"
}
}
]
).forEach((obj) => {
var item = db.shp_counties_with_index.findOne({
geom_geojson: {
$nearSphere: {
$geometry: obj.centroid
}
}
}, { 'name_1': 1, 'name_2': 1 });
});
shp_counties_with_index sample collection
{
"_id" : ObjectId("5846bf55834d5b761f00000a"),
"engtype_2" : "County",
"geom_geojson" : {
"type" : "MultiPolygon",
"coordinates" : [
[
[
[
-73.6516685561232,
34.2445059658098
],
[
-73.6516685623318,
34.2445059757618
],
[
-73.6516685538257,
34.244505973301
],
[
-73.6516685561232,
34.2445059658098
]
]
] ]
},
"name_0" : "United States",
"name_1" : "Michigan",
"name_2" : "Chippewa",
"shape_area" : "0.481851809544",
"shape_leng" : "9.37720288177",
"type_2" : "County",
"validfr_2" : "Unknown",
"validto_2" : "Unknown",
"centroid" : {
"coordinates" : [
-73.65166855807875,
34.244505970785795
],
"type" : "Point"
}
}
shp_tx_survey_with_index sample collection
{
"_id" : ObjectId("5846bf76834d5b761f013fa7"),
"abstract_" : "321.000000000",
"abstract_i" : "322.000000000",
"anum" : "443962",
"area" : "0.0000666764235294",
"geom" : "01060000000100000001030000000100000008000000EC90DE47A07659C0F062332AEA813E403471FBB0A17759C06082096CE6813E4034A2C2ABA17759C0700AAF2731823E40B49BADAAA17759C09092F09440823E401C588E90A17759C000B4279A6A823E400019834C677559C02026721261823E403073564B677559C080C77880E6813E40EC90DE47A07659C0F062332AEA813E40",
"geom_geojson" : {
"type" : "MultiPolygon",
"coordinates" : [
[
[
[
-73.6517272344497,
34.2444627902475
],
[
-73.6517271719931,
34.2444627964974
],
[
-73.6517271718375,
34.2444627914072
],
[
-73.6517272344497,
34.2444627902475
]
]
]
]
},
"geom_text" : "MULTIPOLYGON(((-73.6517272344497 34.2444627902475,-73.6517271719931 34.2444627964974,-73.6517271718375 34.2444627914072,-73.6517272344497 34.2444627902475)))",
"gid" : "271508",
"l1surnam" : "TEMPLETON, J S",
"l2block" : null,
"l3surnum" : "4",
"l4surnam" : null,
"perimeter" : "0.0735082380545",
"probflag" : "0",
"shape_area" : "0.0000666764230571",
"shape_leng" : "0.0735082374282",
"centroid" : {
"coordinates" : [
-73.6517272031436,
34.24446279337245
],
"type" : "Point"
}
}
Thanks in advance.
When you want to combine information from 2 collections in a aggregation pipeline you can use the $lookup operator.
This operator is available from MongoDB 3.2 and up.

mongo $unwind and sum individually the third value of returning and new visitors

From the following document example:
{
"_id" : ObjectId("528e4798bfa9782c078b4662"),
"query" : {
"start-date" : ISODate("2013-11-19T00:00:00Z"),
"end-date" : ISODate("2013-11-20T00:00:00Z"),
"ids" : "ga:69564270",
"dimensions" : "ga:visitorType,ga:visitCount",
"metrics" : [
"ga:organicSearches"
]
},
"columnHeaders" : [
{
"name" : "ga:visitorType",
"columnType" : "DIMENSION",
"dataType" : "STRING"
},
{
"name" : "ga:visitCount",
"columnType" : "DIMENSION",
"dataType" : "STRING"
},
{
"name" : "ga:organicSearches",
"columnType" : "METRIC",
"dataType" : "INTEGER"
}
],
"totalsForAllResults" : {
"ga:organicSearches" : 119
},
"rows" : [
[
"New Visitor",
"1",
100
],
[
"Returning Visitor",
"11",
1
],
[
"Returning Visitor",
"2",
10
],
[
"New Visitor",
"3",
4
],
[
"Returning Visitor",
"4",
1
],
[
"Returning Visitor",
"5",
1
],
[
"New Visitor",
"6",
1
],
[
"New Visitor",
"8",
1
]
],
"query_name" : "GA Organic Traffic Metric",
"profile_id" : 666,
"retrieve_date" : ISODate("2013-11-21T17:49:12Z")
}
How can I use the mongo aggregate framework:
1 To group and project the sum of: New visitors by "query.start-date"
2 To group and project the sum of: Returning Visitors by "query.start-date"
Currently, as You can see "ga:organicSearches" I am having the sum of both, but I need each type of visitors individually, something like "ga:organicSearchesReturningVisitors" and "ga:organicSearchesNewVisitors".
Thanks in advance.
As long as you are okay doing two aggregations, you can do it this way (I'm assuming each document represents one day):
New visitors:
db.visitors.aggregate({$unwind:"$rows"},
{$match:{"rows.0":"New Visitor"}},
{$unwind:"$rows"},
{$match:{"rows":{$type:1}}},
{$group:{_id:"$query.start-date",newVisitorsSum:{$sum:"$rows"}}});
{ "_id" : ISODate("2013-11-19T00:00:00Z"), "newVisitorsSum" : 106 }
Returning visitors:
db.visitors.aggregate({$unwind:"$rows"},
{$match:{"rows.0":"Returning Visitor"}},
{$unwind:"$rows"},
{$match:{"rows":{$type:1}}},
{$group:{_id:"$query.start-date",retVisitorsSum:{$sum:"$rows"}}});
{ "_id" : ISODate("2013-11-19T00:00:00Z"), "retVisitorsSum" : 13 }