I have a Node.js program that is using Mongo Atlas search indexes and is utilizing the Aggregate function inside of the MongoDB driver. In order to search, the user would pass the search queries inside of the query parameters of the URL. That being said, I am trying to build a search object based on if a query parameter exists or not. In order to build the search object I am currently using object spread syntax and parameter short-circuiting, like so:
const mustObj = {
...(query.term && {
text: {
query: query.term,
path: ['name', 'description', 'specs'],
fuzzy: {
maxEdits: 2.0,
},
},
})
}
This is a shortened version, as there are many more parameters, but you get the jest.
In a MongoDB search query, if you have multiple parameters that must meet a certain criteria, they have to be included inside of an array called must, like so:
{
$search: {
compound: {
must: [],
},
},
}
So, in order to include my search params I must first turn my mustObj into an array of objects using Object.keys and mapping them to an array, then assigning the searches 'must' array to the array I've created, like so:
const mustArr = Object.keys(mustObj).map((key) => {
return { [key === 'text2' ? 'text' : key]: mustObj[key] };
});
searchObj[0].$search.compound.must = mustArr;
What I would like to do is, instead of creating the mustObj and then looping over the entire thing to create an array, is to just create the array using the spread syntax and short-curcuiting method I used when creating the object.
I've tried the below code, but to no avail. I get the 'object is not iterable' error:
const mustArr = [
...(query.term && {
text: {
query: query.term,
path: ['name', 'description', 'specs'],
fuzzy: {
maxEdits: 2.0,
},
},
})
]
In all, my question is, is what I'm asking even possible? And if so, how?
Corrected based on #VLAZ comment:
while spread with array [...(item)], item has to be array (iterable).
When you use short-circuit, the item as below,
true && [] ==> will be `[]` ==> it will work
false && [] ==> will be `false` ==> wont work (because false is not array)
try some thing like (Similar to #Chau's suggestion)
const mustArr = [
...(query.term ? [{
text: {
query: query.term,
path: ['name', 'description', 'specs'],
fuzzy: {
maxEdits: 2.0,
},
},
}] : [])
]
Related
I have an object that contains data to display information pulled from the Notion API. I can see the data but not sure how I can extract nested array inside the current array. My goal is to use the category property to create a filter but first I need to get the string to create the condition.
Here is what the data looks like currently. How would I go about to filter out name: "commissions":
resultsArray:
0:
properties
category:
id: "sdasd"
multi_select:
0:
id:"324234"
name: "commissions"
I have tried use find but it doesn't do what I expect. My suspicion is that I will have to loop over the nested array again.
You can use find inside find condition
like this :
data.resultsArray.find(item=>item.category.multi_select.find(select=> select.name === "commissions"))
const data = {
resultsArray: [
{
category: {
id: 'sdasd',
multi_select: [
{
id: '324234',
name: 'commissions',
},
],
},
},
],
};
const result = data.resultsArray.find(item=>item.category.multi_select.find(select=> select.name === "commissions"))
console.log(result)
I'm currently getting data from a database of an array of objects. I need these objects to be reformatted to work with a UI package that we're using that requires these objects to look a specific way. The main array should look like this:
[{
trim: 123,
id: 123,
children: [{
trim: 123,
id: 123,
}],
}]
I'm successfully looping through the main array data and reformatting it into a new array using .map; however, I'm having issues doing the same thing but for the children key that's found in each object of the main array. Wondering if anyone could help me figure out the proper way to do this. I'll add my current code below and will be able to clarify more if needed.
if (this.$store.state.models.models) { // this is checking for the main array coming from the database
const reformattedModels = this.$store.state.models.models.map((model) => {
const tableModel = {
trim: model.name,
id: model.id,
children: // Need to loop here to reformat array of objects that goes for the children key,
};
return tableModel;
});
return reformattedModels;
}
The array that I need to loop through for the children key is one of the keys found in the main array from the backend. It's called "trims" and looks like this:
[{
name: 123,
id: 123,
}]
Create a reference to the function and call it recursively:
if (this.$store.state.models.models) {
// store the function
const mapper = model => ({
trim: model.name,
id: model.id,
// use it for children, if there are any
children: model.children?.map(mapper)
});
// use it for the models
return this.$store.state.models.models.map(mapper);
}
I'm using optional chaining (?.) to call .map() only if model.children != undefined
This question already has answers here:
Find object by id in an array of JavaScript objects
(36 answers)
Closed 2 years ago.
I have a file with 1000s of json rows like below. Im having difficulties locating a specific key in the array.
example json:
{"connection":"98374"
,"db":"8",
,"timestamp":"159905411631"
,"event":"DataCatch"
,"data":[{"key":"ruleid","value":"111"}
,{"key":"responseid","value":"155-response-4"}
,{"key":"responsetype","value":"Capture"}
,{"key":"reason","value":"ClientVisit"}
,{"key":"subreason","value":""}
,{"key":"score","value":"0.00"}
,{"key":"comment","value":""}]
}
I need to be able to find the "reason" key in the "data" array and replace the "value" with "test". The "data" array doesn't always appear on every json row, only when the "event" "dataCatch" is present.
I can parse it into a variable but I can only call the "data" array as a whole. Any ideas how to target specific values in an array?
Having a little trouble with this in Typescript.
There are any number of ways to go about this, but here's one.
First, parse your JSON into an array of objects.
Each element of the array will then look something like this:
{
connection: '98374',
db: '8',
timestamp: '159905411631'
event: 'DataCatch',
data: [
{ key: 'ruleid', value: '111' },
{ key: 'responseid', value: '155-response-4' },
{ key: 'responsetype', value: 'Capture' },
{ key: 'reason', value: 'ClientVisit' },
{ key: 'subreason', value: '' },
{ key: 'score', value: '0.00' },
{ key: 'comment', value: '' },
],
}
Let's call our array of objects allData, so we can refer to it later.
Now we can begin our "surgery".
We'll work from the inside-out, first looking at what needs to be done to a specific entry in an element's data array.
Here's a function that will do just what we need:
function updateReason(entry) {
if (entry.key === 'reason') {
return { ...entry, value: 'test' };
} else {
return entry;
}
}
This function checks if the provided entry has a key with a value of 'reason', and -- if so -- returns a new entry that is identical to the provided one except its value is 'test'.
How can we use this to update an entire data array (in an entry that has data, that is)?
We simply delegate the work to our dear friend map:
function updateData(data) {
// or simply `data.map(updateEntry);`
return data.map(entry => updateEntry(entry));
}
We're slowly working our way "outwards".
What about updating an entire entry in our big allData array (which may or may not contain data)?
// I've called such an entry a "collection", because I already used the name
// "entry" above :(
// A "collection" is just an entry in the big `allData` array.
function updateCollection(collection) {
if (collection.event === 'DataCatch') {
return {
...collection, // Leave everything else the way it is
data: updateData(collection.data), // But update the `data` array
};
} else {
return collection;
}
}
So close.
The last thing we need to do is apply this transformation to every element of our parsed allData array:
// or `allData.map(updateCollection);`
const updatedData = allData.map(collection => updateCollection(collection));
Also:
Q: Wouldn't it be cheaper to mutate the entry?
A: It would be cheaper, but not that much cheaper, due to a large amount of "structural sharing" that occurs here. I would recommend this approach unless you either need to mutate your input for some reason, or performance requirements demand it.
You need to map over the data key in your data variable like this.
data.data = data.data.map((item) => {
if (item.key === "reason") {
item.value = "test";
}
return item;
});
the data key is an array of values, so you need to loop through it and compare the value of the key property to the value you are looking for, if it matches then you can update the value property
https://codesandbox.io/s/angry-shirley-1gh83?file=/src/index.ts:666-782
Hi I am now using gremlin -javascript to do some queries in AWS neptune DB.
I have a query like
[errRelatedTicket, relatedTicket] = await to(g.V().hasId(a).in_('r').valueMap(true).toList());
then I get a list of map like:
[
Map {
id: 1
},
Map {
id: 2
},
]
But can I use gremlin query to get id and properties in key/value pairs directly instead?
what I expect is:
[
{ id: 1 },
{ id: 2 },
]
I don't know "gremlin-javascript", you can research more in the document. But I know there's a simple way to do the conversion in plain javascript, use .map and Object.fromEntries. Hope you'll find a better way.
var listMap = [
new Map([[ 'id', 1 ]]),
new Map([[ 'id', 2 ]]),
];
var listObject = listMap.map(m => Object.fromEntries(m));
console.log(listObject);
If you always want to return objects rather than maps, you can set this configuration in your DriverRemoteConnection construct, like so: const dc = new DriverRemoteConnection(CLUSTER_URL, { mimeType: 'application/vnd.gremlin-v2.0+json' });
I have an array, clients, which I want to run array.find() on. This array contains objects, and usually looks something like this:
[ { customId: 'user1', clientId: 'TPGMNrnGtpRYtxxIAAAC' },
{ customId: 'user2', clientId: 'G80kFbp9ggAcLiDjAAAE' } ]
This is where I encounter a problem. I am trying to use find() to see if any object (or part of an object) in the array matches a certain variable, recipient, which usually contains a value like user1. the code I am using to do this is:
function checkID(recipient) {
return recipient;
}
var found = clients.find(checkID);
This always returns the first object in the array. Am I using find() wrong, or is there a better way to do this?
find takes a predicate (a function that returns true if item is a match and false if item is not a match).
const arr = [ { customId: 'user1', clientId: 'TPGMNrnGtpRYtxxIAAAC' },
{ customId: 'user2', clientId: 'G80kFbp9ggAcLiDjAAAE' } ]
const result = arr.find(item => item.customId === 'user1')
// ^^^^^^^^^^^^^^^^^^^^^^^^^
// This should evaluate to true for a match and to false for non-match
The reason you're getting the first item of your array all the time, is because your checkId function is returning something which evaluates to true. So, the first item is evaluated and produces a truthy result, and therefore it gets picked as the first match.
If unfamiliar with the lambda syntax () => {}, then that line is similar to:
const result = arr.find(function (item) { return item.customId === 'user1' })
You are using find wrong.
If recipient contains information about the target value you should name the first param of checkID with a different name. And compare any property of it with recipient.
var found = clients.find(function(element) { return element.prop1 === recipient.anyProp; });
To check the objects in the array for the presence of a certain customId, put the value you're searching for in an object, and pass that object to find():
let clients = [{
customId: "user1",
clientId: "TPGMNrnGtpRYtxxIAAAC"
},
{
customId: "user2",
clientId: "G80kFbp9ggAcLiDjAAAE"
}
];
function checkID(el){
return el.customId === this.param;
}
let found = clients.find(checkID, {param: "user1"});
console.info(found);