How to find number of distinct values from a collection - backbone.js

Suppose I have a collection like:
{
"id": 1,
"name": "jonas",
},
{
"id": 2,
"name": "jonas",
},
{
"id":3,
"name": "smirk",
}
How do I get :
Number of distinct names, like in this case, 2
The distinct names, in this case, jonas and smirk ?

With some Backbone and Underscore magic, combining collection.pluck and _.uniq:
pluck collection.pluck(attribute)
Pluck an attribute from each model in the collection. Equivalent to calling map, and returning a single attribute from the iterator.
uniq _.uniq(array, [isSorted], [iterator])
Produces a duplicate-free version of the array, using === to test object equality.
[...]
var c = new Backbone.Collection([
{id: 1, name: "jonas"},
{id: 2, name: "jonas"},
{id: 3, name: "smirk"}
]);
var names = _.uniq(c.pluck('name'));
console.log(names.length);
console.log(names);
And a demo http://jsfiddle.net/nikoshr/PSFXg/

Related

Which is the efficient way of updating an element in MongoDB?

I have a collection like below
{
"doc_id": "1234",
"items": [
{
"item_no": 1,
"item": "car",
},
{
"item_no": 2,
"item": "bus",
},
{
"item_no": 3,
"item": "truck",
}
]
},
I need to update an element inside items list based on a search criteria. My search criteria is, if "item_no" is 3, "item" should be updated to "aeroplane".
I have written the following two approaches in Python to solve this.
Approach 1:
cursor = list(collection.find({"doc_id": 1234}))
for doc in cursor:
if "items" in doc:
temp = deepcopy(doc["items"])
for element in doc["items"]:
if ("item_no" and "item") in element:
if element["item_no"] == 3:
temp[temp.index(element)]["item"] = "aeroplane"
collection.update_one({"doc_id": 1234},
{"$set": {"items": temp}})
Approach 2:
cursor = list(collection.find({"doc_id": 1234}))
for doc in cursor:
if "items" in doc:
collection.find_one_and_update({"doc_id": 1234}, {'$set': {'items.$[elem]': {"item_no": 3, "item": "aeroplane"}}}, array_filters=[{'elem.item_no': {"$eq": 3}}])
Among the above two approaches, which one is better in terms of time complexity?
Use only a query and avoid loops:
db.collection.update({
"doc_id": "1234",
"items.item_no": 3
},
{
"$set": {
"items.$.item": "aeroplane"
}
})
Example here
Note how using "items.item_no": 3 into the find stage you can use $ into update stage to refer the object into the array.
So, doing
{
"doc_id": "1234",
"items.item_no": 3
}
When you use $ you are telling mongo: "Ok, do your action in the object where the condition is match" (i.e., the object in the collection with doc_id: "1234" and an array with items.item_no: 3)
Also if you want to update more than one document you can use multi:true like this example.
Edit: It seems you are using pymongo so you can use multi=True (insted of multi: true) or a cleaner way, using update_many.
collection.update_many( /* your query here */ )

I need to get a nested element in a json array

There is some list of elements in json format, it looks like this:
[{
'id': 0,
"name": "Category name1",
"services": [{
"id": 0,
"name": "Product name1"
}, {
"id": 1,
"name": "Product name2"
}]
},
{
'id': 1,
'name': "Category name2",
"services": [{
"id": 0,
"name": "Product name1"
}, {
"id": 1,
"name": "Product name2"
}]
}
]
I'm trying to get only the entire "services" array from the first category. Conditionally, I'm trying to get it as follows:
this.class = this.http.get('/assets/products.json');
this.class.forEach(element => {
if (element.id == ID) //The ID is obtained when calling the function in which this code is executed
{
console.log(element.services);
}
}
However, this gives me absolutely nothing and "undefined" is output to the console, however, with the same array and under the same conditions on the site https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach it (foreach and console.log) outputs everything I need.
//The same foreach only on the mozilla website
array1.forEach(item => {
if(item.id==1){ //1 вместо ID
console.log(item.services);
}});
Output to the console: Array [Object { id: 0, name: "Product name1"}, Object { id: 1, name: "Product name2"}].
P.S. I don't really need this list of products in the console, I'm trying to pass a variable, but since undefined is passed to the variable, as well as to the console, I can't use the variable and call it to display products on the page. All this is used in the typescript angular project.
The HttpClient methods like get return observables, to which you need to subscribe to in order for the request to even get executed. In your situation, the class property is only holding a reference to the observable returned by calling this.http.get. Try subscribing to the observable and use the result to extract the data that you need.
this.http.get<any[]>('/assets/products.json').subscribe((data) => {
this.class = data;
this.class.forEach((element) => {
if (element.id == ID) {
console.log(element.services);
}
});
});

Filter for items in nested array using lodash

I have an array of > 1000 objects, each with a nested array that looks something like that:
data = [{
"id": 0,
"location": "A",
"basket": [
"milk",
"bread",
"sugar",
"water"
],
}, {
"id": 1,
"location": "B",
"basket": [
"chocolate",
"cereal",
"sugar",
"sauce"
],
}, {
"id": 2,
"location": "C",
"basket": [
"milk",
"cereal",
"soda",
"flour"
],
}]
I have a multi-select dropdown menu that has the list of all items in the "basket" nested array. When I select "sugar", it should be able to return the objects with id=0 and id=1 or if I select both "water" and "milk" should return objects with id=0 and id=2. I have tried using a combination of _.map _.find _.filter, but it doesn't work. Also tried looking for similar questions here, but didn't find one. prefer to use lodash if possible.
You can use this:
var result = _.filter(data, { basket: ['sugar', 'milk'] });
Replace the array of products with whatever you are looking for. They must all occur in the same item for it to be retained in the result.
Although you clearly indicate you prefer a lodash-based solution, I want to add the vanilla JS way as well:
var filtered = data.filter(function(item){
return ['sugar', 'milk'].every(product => item.basket.includes(product));
});
When you want the logic to be that only some of the selected products need to occur in the basket for it to get selected, then also in the lodash version you'll need a callback:
var result = _.filter(data, function(item) {
return _.intersection(item.basket, ['sugar', 'milk']).length;
});
In the vanilla JS version, replace every by some.

How to sort in array of object - CouchBase

Hi currently I want to sort array of object, I use ARRAY_SORT function, it will use the first field of object to sort & it work well if every object has the same JSON structure. If one element in array has different JSON structure, the result is incorrect.
The query I use :
SELECT ARRAY_SORT(c.student) as student FROM Class c
Result :
"student": [
{
"id": 3,
"name": "Kenny35"
},
{
"id": 6,
"name": "Kenny35"
},
{
"id": 7,
"name": "Kenny35"
},
{
"id": 8,
"name": "Kenny35"
},
{
"hobby": "video game",
"id": 5,
"name": "Kenny35"
}
]
How can I specify property of object in array for ARRAY_SORT function ?
dev,
Objects are first compared by length/size of the object, then followed by fields in the object.
http://developer.couchbase.com/documentation/server/4.5/n1ql/n1ql-language-reference/comparisonops.html
That is the only collation supported now.
-Prasad
You can issue a query and use ORDER BY.
SELECT *
FROM Class c
UNNEST c.student s
ORDER BY ...

How to check before updating an array element in MongoDB/NodeJS

In my sample document, I have a campaign document that contains the _id of the document and an importData array. importData is an array of objects containing a unique date and source value.
My goal is to have an object updated with a unique date/source pair. I would like to have the new object replace any matching object. In the example below, Fred may have originally donated a TV, but I want my application to update the object to reflect he donated both a TV and a radio.
// Events (sample document)
{
"_id" : "Junky Joe's Jubilee",
"importData" : [
{
"date": "2015-05-31",
"source": "Fred",
"items": [
{item: "TV", value: 20.00},
{item: "radio", value: 5.34}
]
},
{
"date": "2015-05-31",
"source": "Mary",
"items": [
{item: "Dresser", value: 225.00}
]
}
]
}
My original thought was to do something like the code below, but not only am I updating importData with Fred's donations, I'm also blowing away anything else in the importData array:
var collection = db.collection("events");
collection.update(
{_id: "Junky Joe's Jubilee",
importData: {
date: "2015-05-31",
source: 'Fred'
},
}, // See if we can find a campaign object with this name
{
$set:
{"importData":
{
date: "2015-05-31",
source: 'Fred',
items: [
{item: "TV", value: 20.00},
{item: "radio", value: 5.34}
]
}
}
},
{upsert: true}); // Create a document if one does not exist for this campaign
When I tried pushing (instead of $set), I was getting multiple entries for the date/source combos (e.g. Fred would appear to have donated two items multiple times on "2015-05-31").
How would I go about doing that with the MongoDB native driver and NodeJS?
Try this
var collection = db.collection("events");
collection.update(
{_id: "Junky Joe's Jubilee",
importData: {
date: "2015-05-31",
source: 'Fred'
},
}, // See if we can find a campaign object with this name
{
$set:
{"importData.$":
{
date: "2015-05-31",
source: 'Fred',
items: [
{item: "TV", value: 20.00},
{item: "radio", value: 5.34}
]
}
}
},
{upsert: true}); // Create a document if one does not exist for this campaign
According to the documentation under Array update operators this should only modify the first element in the array, which matches the query.

Resources