Node/Mongo autocomplete with search on two fields - node.js

I am using Node/Express/Mongo/Mongoose/jQuery/jQuery UI Auto-complete. I have a collection of Businesses that look like this:
[
{
name: "Example Corporation",
"address": {
"city": "New York",
"state: "NY"
},
{
name: "ABC Corp",
"address": {
"city": "Atlanta",
"state: "GA"
},
{
name: "ACME Inc",
"address": {
"city": "Dallas",
"state: "TX"
},
{
name: "New York Company",
"address": {
"city": "New York",
"state: "NY"
},
{
name: "XYZ Co",
"address": {
"city": "Newark",
"state: "NJ"
}
}
]
I want to create an auto-complete that would allow someone to type in the partial name of the business name OR city and get results back grouped like so:
If I search "New" I want:
{
businesses: [
{
name: "New York Company",
address: {
"city": "New York",
"state": "NY"
}
},
{
name: "XYZ Co",
address: {
"city": "Newark",
"state": "NJ"
}
}
],
cities: [
{
"city": "New York",
"state": "NY"
},
{
"city": "Newark",
"state": "NJ"
}
]
}
Very similar to an auto-complete search you might see on OpenTable where you can search by restaurant or location. I want unique city names returned.
Do I need to search the collection twice per business name and city and tie it all together at the end? I'm so confused. I don't need ID's back since the end result they either go to a City page or the Business page. I hope this makes sense.

Related

Mongoose findByIdAndUpdate destroys missing fields

Developing a node.js api. I have mongo data that shows venues. It contains an address, for example....
"address": {
"street": "123 main st",
"city": "seomwhere",
"state": "FL",
"zip": "33222"
},
:
When I POST to the update endpoint and send the body like this it does update the address, but it REMOVES all the other fields that were there....
"address": {
"zip": "33222"
}
So, in the db, street, city, state are missing. Here's a piece of my code...
venue = await Venue.findByIdAndUpdate(req.params.id, req.body, {
new: true,
runValidators: true
});
Any ideas why?
Because address contains only single key in the body ("address": { "zip": "33222" }) it replaces the other values inside the address object with the blank ones in the database.
So to overcome the issue you have to use . notation with the address object. Like
venue = await Venue.findByIdAndUpdate(
req.params.id,
{ $set: { "address.zip": "33222" },
{ new: true, runValidators: true }
)
But as you cannot identify which keys inside the address object will be updated and also for the root level
const object = req.body
for (var key in req.body.address) {
object[`address.${key}`] = object.address[key]
}
delete object.address
venue = await Venue.findByIdAndUpdate(
req.params.id,
{ $set: object },
{ new: true, runValidators: true }
)
You are overwriting existing address fields when not specified in the request body.
You need to only update the fields in the request body:
const fields = {};
Object.keys(req.body.address).forEach(key => {
fields[`address.${key}`] = req.body.address[key];
});
const venue = await Venue.findByIdAndUpdate(req.params.id, fields, {
new: true,
runValidators: true
});
Let's say we have this venue document:
{
"_id": "5e047d4e10be4f0da4c61703",
"name": "Venue 1",
"address": {
"street": "123 main st",
"city": "seomwhere",
"state": "FL",
"zip": "33222"
},
"__v": 0
}
When you use a requset body like this:
{
"address": {
"zip": "33333"
}
}
The response will be:
{
"address": {
"street": "123 main st",
"city": "seomwhere",
"state": "FL",
"zip": "33333"
},
"_id": "5e047d4e10be4f0da4c61703",
"name": "Venue 1",
"__v": 0
}
And when we want to update like this:
{
"address": {
"state": "NY",
"zip": "44444"
}
}
The response will be:
{
"address": {
"street": "123 main st",
"city": "seomwhere",
"state": "NY",
"zip": "44444"
},
"_id": "5e047d4e10be4f0da4c61703",
"name": "Venue 1",
"__v": 0
}

How to setup Partial Authentication using Authorize API

Okay I am setting up Partial Payments via the Authorize.net API in order to enable multiple cards to be used to cover a single balance/charge.
I'm assuming thier Partial Auth feature covers my use case, but in testing, there is an issue I can show you using the API live console here: https://developer.authorize.net/api/reference/index.html#payment-transactions-charge-a-credit-card
Go to the link above and authorize partial payments with the request I edited below and you will notice when you press submit you get a splitTenderId:
{
"createTransactionRequest": {
"merchantAuthentication": {
"name": "5KP3u95bQpv",
"transactionKey": "346HZ32z3fP4hTG2"
},
"refId": "123456",
"transactionRequest": {
"transactionType": "authCaptureTransaction",
"amount": "462.25",
"payment": {
"creditCard": {
"cardNumber": "5424000000000015",
"expirationDate": "2020-12",
"cardCode": "999"
}
},
"lineItems": {
"lineItem": {
"itemId": "1",
"name": "vase",
"description": "Cannes logo",
"quantity": "18",
"unitPrice": "45.00"
}
},
"tax": {
"amount": "4.26",
"name": "level2 tax name",
"description": "level2 tax"
},
"duty": {
"amount": "8.55",
"name": "duty name",
"description": "duty description"
},
"shipping": {
"amount": "4.26",
"name": "level2 tax name",
"description": "level2 tax"
},
"poNumber": "456654",
"customer": {
"id": "99999456654"
},
"billTo": {
"firstName": "Ellen",
"lastName": "Johnson",
"company": "Souveniropolis",
"address": "14 Main Street",
"city": "Pecan Springs",
"state": "TX",
"zip": "44628",
"country": "USA"
},
"shipTo": {
"firstName": "China",
"lastName": "Bayles",
"company": "Thyme for Tea",
"address": "12 Main Street",
"city": "Pecan Springs",
"state": "TX",
"zip": "44628",
"country": "USA"
},
"customerIP": "192.168.1.1",
"transactionSettings": {
"setting": [
{
"settingName": "emailCustomer",
"settingValue": "true"
}, {
"settingName": "allowPartialAuth",
"settingValue": "true"
},
]
},
"userFields": {
"userField": [
{
"name": "MerchantDefinedFieldName1",
"value": "MerchantDefinedFieldValue1"
},
{
"name": "favorite_color",
"value": "blue"
}
]
}
}
}
}
This is only successful because the amount is 462.25 as the docs say to use for testing, if I use any other (real) amount the splitTenderId is not there.
Here is a new example request, you can post this again on the link above:
{
"createTransactionRequest": {
"merchantAuthentication": {
"name": "5KP3u95bQpv",
"transactionKey": "346HZ32z3fP4hTG2"
},
"refId": "123456",
"transactionRequest": {
"transactionType": "authCaptureTransaction",
"amount": "462",
"payment": {
"creditCard": {
"cardNumber": "5424000000000015",
"expirationDate": "2020-12",
"cardCode": "999"
}
},
"lineItems": {
"lineItem": {
"itemId": "1",
"name": "vase",
"description": "Cannes logo",
"quantity": "18",
"unitPrice": "45.00"
}
},
"tax": {
"amount": "4.26",
"name": "level2 tax name",
"description": "level2 tax"
},
"duty": {
"amount": "8.55",
"name": "duty name",
"description": "duty description"
},
"shipping": {
"amount": "4.26",
"name": "level2 tax name",
"description": "level2 tax"
},
"poNumber": "456654",
"customer": {
"id": "99999456654"
},
"billTo": {
"firstName": "Ellen",
"lastName": "Johnson",
"company": "Souveniropolis",
"address": "14 Main Street",
"city": "Pecan Springs",
"state": "TX",
"zip": "44628",
"country": "USA"
},
"shipTo": {
"firstName": "China",
"lastName": "Bayles",
"company": "Thyme for Tea",
"address": "12 Main Street",
"city": "Pecan Springs",
"state": "TX",
"zip": "44628",
"country": "USA"
},
"customerIP": "192.168.1.1",
"transactionSettings": {
"setting": [
{
"settingName": "emailCustomer",
"settingValue": "true"
}, {
"settingName": "allowPartialAuth",
"settingValue": "true"
},
]
},
"userFields": {
"userField": [
{
"name": "MerchantDefinedFieldName1",
"value": "MerchantDefinedFieldValue1"
},
{
"name": "favorite_color",
"value": "blue"
}
]
}
}
}
}
And with the 462 amount entered this is no longer a partial auth payment and I no longer get a splitTenderId.
Can someone please help me figure out what is going on?

Bot framework V4 how to add facebook receipt with discount

Is it possible to use the Discount option from Facebook Messenger's Receipt Template with Bot Framework V4?
Because I tried searching the samples, but they require string values, while the Facebook Template requires arrays.
Example:
"adjustments":[
{
"name":"New Customer Discount",
"amount":20
},
{
"name":"$10 Off Coupon",
"amount":10
}
],
Facebook Templates can be sent using ChannelData. Here is an example of a receipt template with adjustments:
await context.sendActivity({
text: 'Receipt',
channelData: {
"attachment":{
"type":"template",
"payload": {
"template_type": "receipt",
"recipient_name": "Stephane Crozatier",
"order_number": "12345678902",
"currency": "USD",
"payment_method": "Visa 2345",
"order_url": "http://petersapparel.parseapp.com/order?order_id=123456",
"timestamp": "1428444852",
"address": {
"street_1": "1 Hacker Way",
"street_2": "",
"city": "Menlo Park",
"postal_code": "94025",
"state": "CA",
"country": "US"
},
"summary": {
"subtotal": 75.00,
"shipping_cost": 4.95,
"total_tax": 6.19,
"total_cost": 56.14
},
"adjustments": [{
"name": "New Customer Discount",
"amount": 20
},
{
"name": "$10 Off Coupon",
"amount": 10
}
],
"elements": [{
"title": "Classic White T-Shirt",
"subtitle": "100% Soft and Luxurious Cotton",
"quantity": 2,
"price": 50,
"currency": "USD",
"image_url": "http://petersapparel.parseapp.com/img/whiteshirt.png"
},
{
"title": "Classic Gray T-Shirt",
"subtitle": "100% Soft and Luxurious Cotton",
"quantity": 1,
"price": 25,
"currency": "USD",
"image_url": "http://petersapparel.parseapp.com/img/grayshirt.png"
}
]
}
}
}
});

Extracting some fields from an object in mongodb

I am new to mongoDB and I am unable to figure out how to extract only few fields from an object in a collection.I have a collection named recipe which is as follow:-
[
{
"_id": "b44e864d-de8f-4110-b676-bbee13417b2e",
"title": "Fried Eggs",
"ingredients": [
{
"name": "Eggs",
"amount": "10"
},
{
"name": "Olive Oil",
"amount": "2 tbs"
}
],
"steps": [
"1. Heat the pan",
"2.Add Olive Oil",
"3. Add Eggs",
"4. Saute"
],
"comments": [
{
"_id": "8604e67c-2426-4742-bc91-25ee1c4064b5",
"poster": "Ron Swanson",
"comment": "Wrong instructions, Got stuck in Toaster"
},
{
"_id": "040412bc-9046-49ca-9a65-19151b32cd91",
"poster": "Tom Haverford",
"comment": "What are Eggs?"
},
{
"_id": "1034f082-b802-4382-be3e-ef50f07a530a",
"poster": "Andy Dwyer",
"comment": "What came firsst, Eggs or Chicken"
}
]
},
{
"_id": "da6f9798-6547-42f5-85ed-043efabeb196",
"title": "Boiled Eggs",
"ingredients": [
{
"name": "Eggs",
"amount": "5"
},
{
"name": "Water",
"amount": "3 Cups"
}
],
"steps": [
"1.Boil the Water",
"2.Add Eggs",
"3. Keepit for 5 mins",
"4. Let it Cool Down",
"5. Peel off the shell"
],
"comments": [
{
"_id": "cc569ebb-1307-499a-b9ee-7b24e557859f",
"poster": "Ron Swanson",
"comment": "Wrong instructions, Got stuck in Oven"
},
{
"_id": "4f02756a-6e1b-4bda-a928-b3c5e03b55d8",
"poster": "Leslie Knope",
"comment": "What are Eggs?"
},
{
"_id": "0f34a5cc-ebe3-41b5-8f0b-6d1a3c206e6b",
"poster": "Andy Dwyer",
"comment": "Can I remove the shell first and then boil?"
}
]
}]
I want to extract only the title and id of both the recipes when a given route is accessed. Currently,I am using this function, which return all the field of both the recipes.
var recipesCollection = db.collection("recipes");
exports.getAllRecipes = function() {
return recipesCollection.find({}).toArray();
};
What query should I use to extract just the title and id of the two recipes and not all the details?
As per my understanding you are trying to fetch specific fields form the mongo collection. You can achieve this just by using the projection.
var recipesCollection = db.collection("recipes");
exports.getAllRecipes = function() {
return recipesCollection.find({}, {"title": 1}).toArray();
};
For more information follow this:
https://docs.mongodb.com/v3.2/tutorial/project-fields-from-query-results/#return-the-specified-fields-and-the-id-field-only

How to customize JSONBuilder results in Groovy?

The below Groovy code produces the result shown under Current Result. How do I customize the JSON output as shown in Expected Output?
def resultset = Sql.newInstance(...).rows('select * from client')
println new JsonBuilder(clients:resultset).toPrettyString()
Current Result
{
"clients": [
{
"ID": 1,
"NAME": "ABC",
"ADDR1": "123 MAIN ST",
"ADDR2": "NEW YORK",
"ZIP": "12345"
},
{
"ID": 2,
"NAME": "XYZ",
"ADDR1": "321 MAIN ST",
"ADDR2": "NEW JERSEY",
"ZIP": "98761"
}
]
}
Do I need to loop through each row and customize?
Expected
{
"clients": [
{
"ID": 1,
"NAME": "ABC",
"CONTACT": {
"ADDR1": "123 MAIN ST",
"ADDR2": "NEW YORK",
"ZIP": "12345"
}
},
{
"ID": 2,
"NAME": "XYZ",
"CONTACT": {
"ADDR1": "321 MAIN ST",
"ADDR2": "NEW JERSEY",
"ZIP": "98761"
}
}
]
}
The code below should work (but I'm not sure cause there's no full example provided):
println new JsonBuilder(clients:resultset.collect {[
ID: it.ID,
NAME: it.NAME,
CONTACT: [
ADDR1: it.ADDR1,
ADDR2: it.ADDR2,
ZIP: it.ZIP,
],
]}).toPrettyString()
Try it and let me know in case of any problems. Do You understand how it works?

Resources