Struggling with Data Rearrangement using Map Reduce技

I'm struggling with pivoting my dataset using map reduce. Despite referencing the MongoDB cookbook for guidance, I'm encountering some strange errors. I aim to restructure the provided collection so that each user has a comprehensive list of all review ratings.

Here's how my collection is structured:

{
  'type': 'review',
  'business_id': (encrypted business id),
  'user_id': (encrypted user id),
  'stars': (star rating),
  'text': (review text),
}

Python-wrapped Map function:

map = Code(""""
function(){
key = {user : this.user_id};
value = {ratings: [this.business_id, this.stars]};

emit(key, value);
}
""")

The map function should output an array of values linked to the key... Python-wrapped Reduce function:

reduce = Code("""
function(key, values){
var result = { value: [] };
temp = [];

for (var i = 0; i < values.length; i++){
temp.push(values[i].ratings);
}
result.value = temp;
return result;
}
""")

However, the results return one less rating than expected. Additionally, some users are receiving 'None' as output, which should not occur. Here are examples of problematic entries:

{u'_id': {u'user: u'zwZytzNIayFoQVEG8Xcvxw'}, u'value': [None, [u'e9nN4XxjdHj4qtKCOPQ_vg', 3.0], None, [...]...]

I'm struggling to identify the underlying issue in my code. When there are 3 reviews, all containing business IDs and ratings in the document, it becomes puzzling. Also, for some reason, using 'values.length + 1' in my loop condition disrupts 'values[i]'.

Edit 1

I've acknowledged that the reducer is repeatedly called on itself, so I've revised my approach. The updated reducer now returns an array of [business, rating, business, rating]. Any suggestions on how to generate [business, rating] arrays instead of one large array?

function(key, value){
var result = { ratings:[] };
var temp = [];
values.forEach(function(value){
    value.ratings.forEach(function(rating){
        if(temp.indexof(rating) == -1){
            temp.push(rating);
        }
    });
});

result. rartings = temp;
return result;
}

Answer №1

Let's try a sample scenario:

1) Introduce some test data:

db.test.drop();
db.test.insert(
  [{
    'type': 'review',
    'business_id': 1,
    'user_id': 1,
    'stars': 1,
  },
  {
    'type': 'review',
    'business_id': 2,
    'user_id': 1,
    'stars': 2,
  },
  {
    'type': 'review',
    'business_id': 2,
    'user_id': 2,
    'stars': 3,
  }]
);

2) Create a mapping function

var map = function() {
  emit(this.user_id, [[this.business_id, this.stars]]);
};

Defining the desired outcome in the map function is crucial, especially when dealing with single user reviews without requiring a reduce phase.

3) Implement a reduction function

var reduce = function(key, values) {
  var result = { ratings: [] };
  values.forEach(function(value){
    result.ratings.push(value[0]);
  });

  return result;
};

Collect all values, considering the nested structure from the map method, and extract the first value from each result set.

4) Execute the map-reduce operation:

db.test.mapReduce(map, reduce, {finalize: final, out: { inline: 1 }});

Alternatively, utilize the aggregation framework:

db.test.aggregate({
  $group: {
    _id: "$user_id", 
    ratings: {$addToSet: {business_id: "$business_id", stars: "$stars"}}
  }
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Modify an element within a BSON record

I need to modify a specific object within my BSON document in mongoose. I am looking to change the status from 0 to 1 where tagID is kLawOURVpz1IIjoQ2fhCvy7NM, tagUnit is 8, and tagNo is 2 I attempted the following: db.updateOne( { "fileID": &q ...

The target for ajaxSubmit is being duplicated instead of being replaced

I encountered a problem with the code below: $('#refresh').click(function () { alert($('.report-container').length); $('.report-container').each(function () { var accordian = this; var url = $(this) ...

What is the best way to extract key/value pairs from an object in javascript that have a specific suffix?

I'm dealing with an object: { a_suff:"Something", b_suff: "Value", c: "Value", d: "Value, e_suff: "Value" } I'm looking for a way to extract all the keys that end in "_suff". What would be the most efficient solution? Currently, I have this im ...

Unable to insert controller into routeprovider

Currently, I am working on an exercise in AngularJS to enhance my skills focusing on routes. However, I am facing issues with getting the controller attributes to function correctly inside the routed template. Despite reading numerous tutorials, the code s ...

Is there a way to create a bar chart that begins at the 0 point of the y-axis instead of starting from the base of the SVG?

Is there a way to start the bar chart from the 0 point of the y-axis instead of the very bottom of the svg? How can I achieve this? let url = "https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/GDP-data.json"; const padding = 5 ...

What strategies can be implemented to effectively share code between these two methods?

Is there a way to consolidate code shared between these two JavaScript methods? async getAllActiveRooms(ctx: ?ContextType): Promise<RoomType[]> { //log getAllActiveRooms return this.i.knex('users_rooms') .transacting(ctx ...

The display of options in React Bootstrap typeahead is not functioning properly

When I try to implement React Bootstrap Typeahead, the options do not appear in the Typeahead component upon page load. Here is a snippet of my code: const React = require('react'); ... (code continues) The options are generated as follows: [ ...

Can we trigger a POST request when the user reaches the bottom of the page?

Many inquiries share this issue, but the solutions I've come across only explain how JavaScript functions, not how to handle routing in this context. I'm currently struggling with implementing the HTML and routing components for an infinite scro ...

What could be causing the error message 'Uncaught SyntaxError: Identifier 'randFilmIndex' has already been declared'?

function getRandomInt(min, max) { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min) + min); } function arrayRemove(arr, value) { return arr.filter(function(ele){ return ele != valu ...

Is there a way to stop mongosh from storing the db.auth password in the repl history?

After executing db.auth("myusername", "mypassword") in a session of mongosh, I noticed that my password is being stored in plain text in the file .mongodb/mongosh/mongosh_repl_history located in my home directory. What steps can I take ...

Using the spread syntax to eliminate a property from an object within a ReactJs element

I'm trying to figure out if it's possible to remove a specific object property using spread syntax when rendering a React component. I want to achieve this without adding too much extra code. Currently, I am utilizing {reset,...inputName} In my ...

Seeking assistance with transmitting data to the server and retrieving it for use. I am looking to achieve this goal utilizing JavaScript with Node.js

I've been experiencing challenges with the interactions between front-end and back-end. I am confident that I am sending the data, but unfortunately, I am unable to access it afterwards. Recently, I utilized this code template (sourced from Mozilla&ap ...

How can I update my EJS template in ExpressJS after retrieving JSON data using NodeJS?

Utilizing NodeJS, I am making API calls and passing the data to my EJS template through ExpressJS with the following code snippet: app.get('/', function (req, res) { res.render('routes/index', { plLoopTimes: plLoopTimes, pl54Ti ...

Replacing the yellow autofill background

After much effort, I have finally discovered the ultimate method to remove autofill styling across all browsers: $('input').each(function() { var $this = $(this); $this.after($this.clone()).remove(); }); However, executing t ...

Sorting two different divisions is an example

I need advice on how to toggle between two divs, A and B, without having to reload the page. Ideally, I would like to have three buttons - one that shows only div A when clicked, another that displays only div B, and a third button that shows both A and ...

The function google.script.run encounters an error when dealing with file inputs

For the past two years, my Google Apps Script connected to a spreadsheet has been working flawlessly. I created an HTML form to upload CSV and Excel files for processing and data loading into the spreadsheet. However, since March 2020, file uploading has b ...

Choose all items on each page with Material-UI's table pagination

Can items be selected solely on the current page or per page within the Table? Check out this demo for reference. ...

Searching for items in a MongoDB collection using an array of values from a different collection

If I were to develop a sticker albums app where users can purchase albums and stickers, the relationship between users and albums would be many-to-many. Consider an example of my user collection: {"_id":{"$oid":"61a04f49909f8e972f5 ...

Transmitting payment card details to the node

I'm considering utilizing dibs payment dibspayment I came across this Node.js wrapper for the: DIBS API wrapper for Node.js However, using this would involve sending credit card information through a POST request to my node server. My main concern ...

Apply various filters to extract and refine information from the database

I have successfully retrieved data from the database. The structure of the data is as follows: serie --- title (string) --- category (array) To filter the data, I have implemented a search filter using a computed property. This is how it looks: f ...