Uploaded image for project: 'Documentation'
  1. Documentation
  2. DOCS-14337

Map-Reduce Examples Docs Page - wrong or misleading examples

      Description

      One of the freelancer writers that is writing an article for the SEO-Hygiene initiative (Content Marketing & Growth Teams) got stuck on writing some sample code examples with Node.js driver for the example of using MongoDB mapReduce.
       
      My team, Developer Advocate team, notice a couple things on the reference documentation that needs to be more clear:

      • in JS in general array.sum does not look correct, it should be array.reduce

       


      For Context the thread of the email of the freelancer writer:

      At any rate, back to the issues with mapReduce; I attempted to run the following code:

      """
      await collection.mapReduce(
              function() {
                  emit(1, this.itemsTotal)
              },
              function(key, values) {
                  return Array.sum(values)
              }
          )
      """

      According to the Node driver's .d.ts files, this is valid usage. However, I got the error:

      """
      TypeError: Cannot read property 'out' of undefined
          at Collection.mapReduce
      """

      So, looking back at the docs page, I saw that there was a string assigned to "out":

      """
      await collection.mapReduce(
              function() {
                  emit(1, this.itemsTotal)
              },
              function(key, values) {
                  return Array.sum(values)
              },
              {
                  out: "Test"
              }
          )
      """

      Not only did I get errors from typescript saying that "out" needed to be an object, I got the same error as before.

      However, with some searching online, I found that you're able to change the last config object to:

      """
      {
      out: { inline: 1 }
      }
      """

      Once I did this, I got an array of values, without commas, not combined in any way, returned to the console.

      Code:

      """
      await collection.mapReduce(
              function() {
                  emit(1, this.itemsTotal)
              },
              function(key, values) {
                  return Array.sum(values);
              },
              {
                  out: { inline: 1 }
              }
          )
      """

      Output (shortened):

      """
      [{"_id":1,"value":"NumberDecimal(\"1863.46\")NumberDecimal(\"798.25\")NumberDecimal(\"756.90\")NumberDecimal(\"758.22\")NumberDecimal(\"233.58\")NumberDecimal(\"122.05\")NumberDecimal(\"1628.90\")NumberDecimal(\"355.79\")NumberDecimal(\"1200.78\")NumberDecimal(\"719.72\")
      """

      Not knowing how Array.sum works (it's not valid JS, but it's documented as the way to combine an array of numbers from the docs page), I decided to use `values.reduce` to manually add the numbers together:

      """
       await collection.mapReduce(
              function() {
                  emit(1, this.itemsTotal)
              },
              function(key, values) {
                  return values.reduce((p: number, c: any) => p + c, 0)
              },
              {
                  out: { inline: 1 }
              }
          )
      """

      However, I ended up just getting `0` as a string appended at the start

      """
      [{"_id":1,"value":"0NumberDecimal(\"1863.46\")NumberDecimal(\"798.25\")NumberDecimal(\"756.90\")NumberDecimal(\"758.22\")NumberDecimal(\"233.58\")
      """

      I then decided to try and get the value of `NumberDecimal`.

      I tried using `parseInt` on `c`, which left me with `0` as a final result. I assume this is because `parseInt(Object)` is `NaN`

      The only way I was able to get the results of the numbers combined was the following code:

      """
       await collection.mapReduce(
              function() {
                  emit(1, this.itemsTotal)
              },
              function(key, values) {
                  return values.reduce((p: number, c: any) => p + Number(JSON.parse(JSON.stringify(c))["$numberDecimal"], 0)
              },
              {
                  out: { inline: 1 }
              }
          )
      """

      However, this seems like an obvious anti-pattern and I wouldn't feel comfortable putting this as official docs that I wrote.

      Just to make sure this wasn't a bug in the NodeJS driver, I attempted to use the Mongo Shell:

      """
      use("sample_supplies");

      db.sales.mapReduce(
          function() {
              emit(1, this.itemsTotal)
          },
          function(key, values) {
              return values.reduce((p, c) => p + c, 0)
          },
          {
              out: { inline: 1 }
          }
      )
      """

      And ran into the same issues as before (I tried all of the code variations I outlined for NodeJS as well with the same results)

       

      Scope of changes

      Impact to Other Docs

      MVP (Work and Date)

      Resources (Scope or Design Docs, Invision, etc.)

            Assignee:
            Unassigned Unassigned
            Reporter:
            r.rodrigues@mongodb.com Rita Martins Rodrigues (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              1 year, 24 weeks, 4 days ago