Couchbase View _count Reduce For Given Keys - mapreduce

I am trying to write a view in Couchbase using a reduce such as _count which will give me a count of the products at an address.
I have some documents in the database in the following format;
Document 1
{
id: 1,
address: {
street: 'W Churchill St'
city: 'Chicago',
state: 'IL',
},
product: 'Cable'
}
Document 2
{
id: 2,
address: {
street: 'W Churchill St'
city: 'Chicago',
state: 'IL',
},
product: 'Cable'
}
Document 3
{
id: 3,
address: {
street: 'W Churchill St'
city: 'Chicago',
state: 'IL',
},
product: 'Satellite'
}
Document 4
{
id: 4,
address: {
street: 'E Foster Rd'
city: 'New York',
state: 'NY',
},
product: 'Free To Air'
}
I already have a view which gives me all the products at an address which uses a composite key such as;
emit([doc.address.street, doc.address.city, doc.address.state], null)
Now this leads me on to the actual problem, I want to be able to get a count of products at a address or addresses.
I want to be able to see for an array of "keys"
['W Churchill St','Chicago','IL']
['E Foster Rd','New York','NY']
which products and a count of them. So i would expect to see in my results.
'Cable' : 2,
'Satellite': 1,
'Free To Air': 1
however if I specified only this "key",
['W Churchill St','Chicago','IL']
I would expect to see
'Cable' : 2,
'Satellite': 1
How to write my view to accommodate this?

The solution to this was to append my product to the key like so;
emit([doc.address.street, doc.address.city, doc.address.state, doc.product], null)
Then using;
?start_key=[street,city,state]&end_key=[street,city,state,{}]&group_level=4
Result:
{"rows":[
{"key":['W Churchill St','Chicago','IL','Cable'], "value":2},
{"key":['W Churchill St','Chicago','IL','Satellite'], "value":1}
]}
I would then need to repeat this query for each of the addresses and sum the results.

Related

boost: read_json: reading multiple lines

When reading the below JSON data, am getting invalid code sequence exception
in read_json.
{
"_ID":"18",
"_Record":"1",
"_BreakPageMessage":"abcd: 137
Product: ID: 1234
Description: 23456 abcdfm
CustomerId: 23456
Component Id: 3456
Description: 12345 Admn RC - up
count: 40
Sides 2
Tarnish:
size: 125 x 205
Memo:"
}
_BreakPageMessage property has multiple lines. If we give it as single line everything works fine.
This _BreakPageMessage doesn't have any umlaut characters.
boost::property_tree::read_json( file, pt );
Can anyone tell is there anyway to read json that has multiple lines of property data using boost.We are using C++ and boost.
Newlines are not valid characters in JSON strings, your data isn't JSON.
You could escape them
{
"_ID":"18",
"_Record":"1",
"_BreakPageMessage":"abcd: 137\r\n Product: ID: 1234\r\n Description: 23456 abcdfm\r\n CustomerId: 23456\r\n Component Id: 3456\r\n Description: 12345 Admn RC - up\r\n count: 40\r\n Sides 2\r\n Tarnish:\r\n size: 125 x 205\r\n Memo:"
}
or use a sub-object
{
"_ID":"18",
"_Record":"1",
"_BreakPageMessage":{
"abcd": 137,
"Product": { "ID": 1234 },
"Description": "23456 abcdfm",
"CustomerId": "23456",
"Component Id": "3456",
"Description": "12345 Admn RC - up",
"count": "40",
"Sides": "2",
"Tarnish": { size: "125 x 205" },
"Memo":""
}
}

How to use if condition in Karate

Suppose I have the following Json response
[
{
id: 1,
name: "John",
password: "JohnsPassword54",
},
{
id: 2,
name: "David",
password: "DavidsPassword24",
}
]
Then how can I extract the array with name David to do further validation?
e.g. I want to say if name == David then save the id
Well done :) Mastering Json-Path is key to get the most out of Karate !
Just for the sake of demo, here is another option, using the get keyword to get the first element out of the array returned, as Json-Path wildcard searches always return an array:
* def response =
"""
[
{
id: 1,
name: "John",
password: "JohnsPassword54"
},
{
id: 2,
name: "David",
password: "DavidsPassword24"
}
]
"""
* def userId = get[0] response $[?(#.name == 'David')].id
* match userId == 2
I found the solution in the Json expression evaluation -
def user = $..[?(#.name == 'David')]
Then I can use the following -
def userId = user[0].id

How do I reorder search results with Semantic UI's local search?

I have a local search box using Semantic 2.1 with an array of hashes.
[{ title: 'Andorra' , rank: 1 } , { title: 'United Arab Emirates', rank: 2 } , { title: 'Afghanistan' , rank: 3 } , { title: 'Antigua' , rank: 4 } ,...]
I would like the search results to be ordered in the order I have the hashes in the array.
For example, searching the countries with the search string Ar, right now I get
Armenia
Argentina
Aruba
Andorra
United Arab Emirates
American Samoa
Austria
But I would like to display
United Arab Emirates
Armenia
Argentina
...
Is there a way to do to do that without rewriting the source?
Here's the demo fiddle I setup: http://jsfiddle.net/zestly/ckxpvgm7/1/
As a bonus question, can anyone explain why American Samoa gets returned?
Only method I know is to override the results HTML creation for the search function using something like this:
$.fn.search.settings.templates = {
standard: function(response) {
// Your own sorting logic here
var sortedResults = response.results.sort(function(a, b) {
if (a.title === 'United Arab Emirates' || b.title === 'United Arab Emirates')
return 1;
else if (a.rank > b.rank)
return 1;
else if (a.rank < b.rank)
return -1;
else
return 0;
});
// Create the DOM as as it normally should be
return $.map(sortedResults, function(item) {
return $('<div>').append($('<a>').addClass('result').append(
$('<div>').addClass('content').append(
$('<div>').addClass('title').text(item.title)
)
)).html();
});
}
};
This is the last time you have access to the results array before it is drawn onto the results container. You can re-arrange it using your own sorting logic and then build up a results DOM which matches what would normally be returned anyway.

Filter data being passed into a crossfilter group without using dimensional filters

I'm trying to figure out how to add a filter onto a crossfilter group that is not related to a dimensional filter. Let's look at an example:
var livingThings = crossfilter({
// Fact data.
{ name: “Rusty”, type: “human”, legs: 2 },
{ name: “Alex”, type: “human”, legs: 2 },
{ name: “Lassie”, type: “dog”, legs: 4 },
{ name: “Spot”, type: “dog”, legs: 4 },
{ name: “Polly”, type: “bird”, legs: 2 },
{ name: “Fiona”, type: “plant”, legs: 0 }
}); //taken from http://blog.rusty.io/2012/09/17/crossfilter-tutorial/
if we were to make a dimension on type and a group of that dimension:
var typeDim = livingThings.dimension(function(d){return d.type});
var typeGroup = typeDim.group();
we would expect typeGroup.top(Infinity) to output
{{human:2},
{dog:2},
{bird:1},
{plant:1}}
My question is how can we filter the data such that they include only 4 legged creatures in this grouping? I also don't want to use dimension.filter... because i don't want this filter to be global, just for this one grouping. In other words
var filterDim = livingThings.dimension(function(d){return d.legs}).filterExact(4);
is not allowed.
I'm thinking of something similar to what I did to post-filter dimensions as in https://stackoverflow.com/a/30467216/4624663
basically I want to go into the internals of the typeDim dimension, and filter the data before it is passed into the groups. Creating a fake group that calls typeDim.group().top() will most likely not work as the individual livingThings records are already grouped by that point. I know this is tricky: thanks for any help.
V
Probably best to use the reduceSum functionality to create a pseudo-count group that only counts records with 4 or more legs:
var livingThings = crossfilter({
// Fact data.
{ name: “Rusty”, type: “human”, legs: 2 },
{ name: “Alex”, type: “human”, legs: 2 },
{ name: “Lassie”, type: “dog”, legs: 4 },
{ name: “Spot”, type: “dog”, legs: 4 },
{ name: “Polly”, type: “bird”, legs: 2 },
{ name: “Fiona”, type: “plant”, legs: 0 }
}); //taken from http://blog.rusty.io/2012/09/17/crossfilter-tutorial/
var typeDim = livingThings.dimension(function(d){return d.type});
var typeGroup = typeDim.group().reduceSum(function(d) {
return d.legs === 4 ? 1 : 0;
});
That will sum across a calculated value that will be 1 for records with 4 legs and 0 for records with ... not 4 legs. In other words, it should just count 4-legged creatures.
I think, this is what you are looking for. Comment back if I'm wrong.
var dimByLegs = livingThings.dimension(function(d){return d.legs});
dimByLegs.filterExact(4);
var dogs = dimByLegs.group();
dimByLegs.top(Infinity).forEach(function(d){console.log(d.type, d.legs);});
dimByLegs.dispose();

Order repeating entries by sum of one field with distinct of another

I looked around and couldn't find a good answer for this, and I'm completely new to Mongo so here is the thing if someone can help.
I have a collection in mongo which holds user related data, in this manner:
{user: 4, rate: 2, location: 1}
{user: 5, rate: 4, location: 1}
{user: 6, rate: 3, location: 1}
{user: 5, rate: 2, location: 1}
{user: 4, rate: 5, location: 1}
...
{user: x, rate: y, location: z}
Now I need a query that will return me all the users on certain location (here is 1 but can be anything) together with final sum of all the rates for that user, and all that ordered by that same sum of rates (hope this makes sense). So something like this :
{4: 7, 5: 6, 6: 3} -> {user: sum(rate)} - ordered by sum(rate)
Any ideas guys?
I will be doing this in mongoengine for Django so if anyone knows how to do this there cool, but if not I'll just do a raw query so any help is good.
Thanks a bunch!
The MongoDB feature you are looking for is the Aggregation Framework.
Here is an example query in the mongo shell:
db.collection.aggregate(
// Find matching documents (can take advantage of suitable index if present)
{ $match: {
location: 1
}},
// Add up rates by user
{ $group: {
_id: "$user",
rates: { $sum: "$rate" }
}},
// Order by total rates (ascending)
{ $sort: { rates: 1 }}
)
Sample results given your data in the question:
[
{
"_id" : 6,
"rates" : 3
},
{
"_id" : 5,
"rates" : 6
},
{
"_id" : 4,
"rates" : 7
}
]
As an optional step in the aggregation, you might want to use $project to rename the grouped _id field to user.