问:
The calls of my own domain repository that extend FE user of TYPO3 7.6 don't work
I have in the model of my own extension a class that extends of FE user of TYPO3 7.6 call CommunityManager, I want to use the calls common to the repository like findByUid() or findAll() but they do not work, the value of return is Null.

I've been researching about it, even in several here questions but it still does not work. I currently have the following settings

In my CommunityManagerController

```<code>/**
 * communityManagerRepository
 *
 * @var \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository
 * @inject
 */
 protected $communityManagerRepository = null;

/**
 * action list
 *
 * @return void
 */
 public function listAction()
  {
    $this->communityManagerRepository = $this->objectManager->get('VENDOR\MyExt\Domain\Repository\CommunityManagerRepository');
    $communityManagers = $this->communityManagerRepository->findAll();
    $this->view->assign('communityManagers', $communityManagers);
  }
</code>```

The CommunityManagerRepository

```<code>class CommunityManagerRepository extends TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository
{
  public function initializeObject()
  {
    $defaultQuerySettings = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings::class);
    $defaultQuerySettings->setRespectStoragePage(false);
    $this->setDefaultQuerySettings($defaultQuerySettings);
  }
 }
</code>```

And the Typoscript code

In constants

```<code>plugin.tx_myext_nameofmyplugin {
  persistence {
    storagePid = 5
  }
}
</code>```

In setup

```<code> config.tx_extbase {
  persistence {
    classes {

      TYPO3\CMS\Extbase\Domain\Model\FrontendUser {
        subclasses {
          Tx_MyExt_CommunityManager = VENDOR\MyExt\Domain\Model\CommunityManager

        }
      }
      VENDOR\MyExt\Domain\Model\CommunityManager {
        mapping {
          tableName = fe_users
          recordType = Tx_MyExt_CommunityManager
        }
      }

    }
  }
}
</code>```

I would appreciate you guiding me to solve the problem

答:
My answer might be too late for this post. But I came across same issue and after debugging extbase classes I found solution.

Your setup is fine; except 1 missing variable recordTypeColumnName (This should be field in record of fe_users table that contains value "Tx_MyExt_CommunityManager").

In my own solution I took advantage of pid column in table row. As I know id of my storage folder, which will remain constant for all my records in extension.

There is 2 ways to set value of recordTypeColumnName:

Method 1:

In TCA set type in ctrl array.

```<code>  $GLOBALS['TCA'][$tableName]['ctrl']['type'] = 'pid';
</code>```

Method 2:

In TypoScript constants.txt

```<code>  PID.myStorage = 5
</code>```

In TypoScript setup.txt

```<code>  plugin.tx_MyExt.persistence.storagePid = {$PID.myStorage}

  config.tx_extbase {
    persistence {
      classes {
        TYPO3\CMS\Extbase\Domain\Model\FrontendUser {
          subclasses {
            {$PID.myStorage} = VENDOR\MyExt\Domain\Model\CommunityManager
          }
          recordTypeColumnName = pid
        }

        VENDOR\MyExt\Domain\Model\CommunityManager {
          mapping {
            tableName = fe_users
            recordType = {$PID.myStorage}
          }
        }
      }
    }
  }
</code>```

Body:
I have in the model of my own extension a class that extends of FE user of TYPO3 7.6 call CommunityManager, I want to use the calls common to the repository like findByUid() or findAll() but they do not work, the value of return is Null.

I've been researching about it, even in several here questions but it still does not work. I currently have the following settings

In my CommunityManagerController

/**
 * communityManagerRepository
 *
 * @var \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository
 * @inject
 */
 protected $communityManagerRepository = null;

/**
 * action list
 *
 * @return void
 */
 public function listAction()
  {
    $this->communityManagerRepository = $this->objectManager->get('VENDOR\MyExt\Domain\Repository\CommunityManagerRepository');
    $communityManagers = $this->communityManagerRepository->findAll();
    $this->view->assign('communityManagers', $communityManagers);
  }

The CommunityManagerRepository

class CommunityManagerRepository extends TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository
{
  public function initializeObject()
  {
    $defaultQuerySettings = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings::class);
    $defaultQuerySettings->setRespectStoragePage(false);
    $this->setDefaultQuerySettings($defaultQuerySettings);
  }
 }

And the Typoscript code

In constants

plugin.tx_myext_nameofmyplugin {
  persistence {
    storagePid = 5
  }
}

In setup

 config.tx_extbase {
  persistence {
    classes {

      TYPO3\CMS\Extbase\Domain\Model\FrontendUser {
        subclasses {
          Tx_MyExt_CommunityManager = VENDOR\MyExt\Domain\Model\CommunityManager

        }
      }
      VENDOR\MyExt\Domain\Model\CommunityManager {
        mapping {
          tableName = fe_users
          recordType = Tx_MyExt_CommunityManager
        }
      }

    }
  }
}

I would appreciate you guiding me to solve the problem

Body:
My answer might be too late for this post. But I came across same issue and after debugging extbase classes I found solution.

Your setup is fine; except 1 missing variable recordTypeColumnName (This should be field in record of fe_users table that contains value "Tx_MyExt_CommunityManager").

In my own solution I took advantage of pid column in table row. As I know id of my storage folder, which will remain constant for all my records in extension.

There is 2 ways to set value of recordTypeColumnName:

Method 1:

In TCA set type in ctrl array.

  $GLOBALS['TCA'][$tableName]['ctrl']['type'] = 'pid';

Method 2:

In TypoScript constants.txt

  PID.myStorage = 5

In TypoScript setup.txt

  plugin.tx_MyExt.persistence.storagePid = {$PID.myStorage}

  config.tx_extbase {
    persistence {
      classes {
        TYPO3\CMS\Extbase\Domain\Model\FrontendUser {
          subclasses {
            {$PID.myStorage} = VENDOR\MyExt\Domain\Model\CommunityManager
          }
          recordTypeColumnName = pid
        }

        VENDOR\MyExt\Domain\Model\CommunityManager {
          mapping {
            tableName = fe_users
            recordType = {$PID.myStorage}
          }
        }
      }
    }
  }


来源: stackexchange

问:
Best practices of disposing of SqlConnection, SqlTransaction, SqlCommand, SqlDataAdapter objects
Are ALL the sqlCommand, sqlTransaction and sqlDataAdapter objects automatically disposed on exit from the "using" block (in which sqlConnection disposed) or all these objects to be disposed should be in separated nested "using" blocks, otherwise these objects will not be disposed when sqlConnection object disposed? What are the best practices?

public static void ExecuteDataset(string connectionString, string storedProcedure, SqlParameter[] sqlParameters = null)
{
    SqlTransaction sqlTransaction = null;

    using (SqlConnection sqlConnection = new SqlConnection(connectionString))
    {
        try
        {
            sqlConnection.Open();

            SqlCommand sqlCommand = new SqlCommand(commandText, connection);
            command.Parameters.Add("@ID", SqlDbType.Int);

            sqlCommand.Connection = sqlConnection;
            SqlTransaction = sqlConnection.BeginTransaction();
            sqlCommand.Transaction = sqlTransaction;
            .....................................................
            .....................................................

            SqlDataAdapter sqlDataAdapter = new SqlDataAdapter();

                ................................
                ................................

            sqlTransaction.Commit();
        }
        catch (Exception)
        {
            sqlTransaction.Rollback();
        }
    }
}
```

答:
If the object implements IDisposable then use using. The underlying implementation details of SqlConnection or SqlCommand or any other object should not matter.

For your scenario the best-practice would be to

```<code>using(var conn = new SqlConnection(...)) {
  ...
  using(var cmd = conn.CreateCommand(...)) {
    ...
  }
  ...
}
</code>```

ContentLicense: CC BY-SA 3.0

Body:
If the object implements IDisposable then use using. The underlying implementation details of SqlConnection or SqlCommand or any other object should not matter.

For your scenario the best-practice would be to

using(var conn = new SqlConnection(...)) {
  ...
  using(var cmd = conn.CreateCommand(...)) {
    ...
  }
  ...
}


问:
How to enable a button after loading the page
I have to disable a button when the page is loading.

How do I enable the button after fully loading the page, using jQuery or JavaScript?

答:
add a disabled property for the button and in the script, document ready function remove disabled function.</p>

```<code>$("#buttonID").prop('disabled',false)
</code>```

ContentLicense: CC BY-SA 4.0

Body:
add a disabled property for the button and in the script, document ready function remove disabled function.

$("#buttonID").prop('disabled',false)


问:
Julia Plotly Plots
I'm trying to do some really basic scatterplots. I'm following instructions from here: https://plot.ly/julia/subplots/

```<code>using Plotly

trace1 = [
  "x" => [1, 2, 3],
  "y" => [4, 5, 6],
  "type" => "scatter"
]
trace2 = [
  "x" => [20, 30, 40],
  "y" => [50, 60, 70],
  "xaxis" => "x2",
  "yaxis" => "y2",
  "type" => "scatter"
]
data = [trace1, trace2]
layout = [
  "xaxis" => ["domain" => [0, 0.45]],
  "yaxis2" => ["anchor" => "x2"],
  "xaxis2" => ["domain" => [0.55, 1]]
]
response = Plotly.plot(data, ["layout" => layout, "filename" => "simple-subplot", "fileopt" => "overwrite"])
plot_url = response["url"]
</code>```

I get:

```<code>ERROR: MethodError: no method matching PlotlyJS.Plot(::Array{Array{Pair{String,Any},1},1}, ::Array{Pair{String,Any},1})
Closest candidates are:
  PlotlyJS.Plot(::AbstractArray{T<:Union{AbstractString, Date, Number, Symbol},1}, ::AbstractArray{T,1} where T) where T<:Union{AbstractString, Date, Number, Symbol} at /Users/username/.julia/v0.6/PlotlyJS/src/convenience_api.jl:56
  PlotlyJS.Plot(::AbstractArray{T<:Union{AbstractString, Date, Number, Symbol},1}, ::AbstractArray{T,1} where T, ::PlotlyJS.Layout; kind, style, kwargs...) where T<:Union{AbstractString, Date, Number, Symbol} at /Users/username/.julia/v0.6/PlotlyJS/src/convenience_api.jl:56
  PlotlyJS.Plot(::AbstractArray{T<:(AbstractArray{T,1} where T),1}, ::AbstractArray{T,2} where T) where T<:(AbstractArray{T,1} where T) at /Users/username/.julia/v0.6/PlotlyJS/src/convenience_api.jl:68
  ...
Stacktrace:
 [1] #plot#36(::Array{Any,1}, ::Function, ::Array{Array{Pair{String,Any},1},1}, ::Vararg{Any,N} where N) at /Users/username/.julia/v0.6/PlotlyJS/src/display.jl:76
 [2] plot(::Array{Array{Pair{String,Any},1},1}, ::Vararg{Any,N} where N) at /Users/username/.julia/v0.6/PlotlyJS/src/display.jl:76
</code>```

I see the errors invoke PlotlyJS vs regular Plotly. I copy/pasted the example code into a fresh Julia shell. I've done Pkg.add("PlotlyJS"), Pkg.add("Plotly"), and Pkg.update(). Still no luck...

答:
My reading of the documentation suggests that this is the kind of approach to try:

```<code>using PlotlyJS

t1 = scatter(;x=[1, 2, 3, 4, 5],
              y=[1, 6, 3, 6, 1],
              mode="lines",
              name="Team A",
              text=["A-1", "A-2", "A-3", "A-4", "A-5"])

t2 = scatter(;x=[1, 2, 3, 4, 5],
             y=[10, 60, 30, 60, 10],
             mode="lines",
             name="Team B",
             text=["B-1", "B-2", "B-3", "B-4", "B-5"])

layout = Layout(;title="Data Labels Hover",
                 xaxis_range=[0, 10],
                 yaxis_range=[0, 100])

data = [t1, t2]

PlotlyJS.plot(data, layout)
</code>```

I think I'd recommend using Plots.jl for local plotting, though (which can use PlotlyJS.jl). Presumably Plotly.jl is for plotting to the cloud?

Title: Julia Plotly Plots

Body:
I'm trying to do some really basic scatterplots. I'm following instructions from here: https://plot.ly/julia/subplots/

using Plotly

trace1 = [
  "x" => [1, 2, 3],
  "y" => [4, 5, 6],
  "type" => "scatter"
]
trace2 = [
  "x" => [20, 30, 40],
  "y" => [50, 60, 70],
  "xaxis" => "x2",
  "yaxis" => "y2",
  "type" => "scatter"
]
data = [trace1, trace2]
layout = [
  "xaxis" => ["domain" => [0, 0.45]],
  "yaxis2" => ["anchor" => "x2"],
  "xaxis2" => ["domain" => [0.55, 1]]
]
response = Plotly.plot(data, ["layout" => layout, "filename" => "simple-subplot", "fileopt" => "overwrite"])
plot_url = response["url"]

I get:

ERROR: MethodError: no method matching PlotlyJS.Plot(::Array{Array{Pair{String,Any},1},1}, ::Array{Pair{String,Any},1})
Closest candidates are:
  PlotlyJS.Plot(::AbstractArray{T<:Union{AbstractString, Date, Number, Symbol},1}, ::AbstractArray{T,1} where T) where T<:Union{AbstractString, Date, Number, Symbol} at /Users/username/.julia/v0.6/PlotlyJS/src/convenience_api.jl:56
  PlotlyJS.Plot(::AbstractArray{T<:Union{AbstractString, Date, Number, Symbol},1}, ::AbstractArray{T,1} where T, ::PlotlyJS.Layout; kind, style, kwargs...) where T<:Union{AbstractString, Date, Number, Symbol} at /Users/username/.julia/v0.6/PlotlyJS/src/convenience_api.jl:56
  PlotlyJS.Plot(::AbstractArray{T<:(AbstractArray{T,1} where T),1}, ::AbstractArray{T,2} where T) where T<:(AbstractArray{T,1} where T) at /Users/username/.julia/v0.6/PlotlyJS/src/convenience_api.jl:68
  ...
Stacktrace:
 [1] #plot#36(::Array{Any,1}, ::Function, ::Array{Array{Pair{String,Any},1},1}, ::Vararg{Any,N} where N) at /Users/username/.julia/v0.6/PlotlyJS/src/display.jl:76
 [2] plot(::Array{Array{Pair{String,Any},1},1}, ::Vararg{Any,N} where N) at /Users/username/.julia/v0.6/PlotlyJS/src/display.jl:76

I see the errors invoke PlotlyJS vs regular Plotly. I copy/pasted the example code into a fresh Julia shell. I've done Pkg.add("PlotlyJS"), Pkg.add("Plotly"), and Pkg.update(). Still no luck...

Body:
My reading of the documentation suggests that this is the kind of approach to try:

using PlotlyJS

t1 = scatter(;x=[1, 2, 3, 4, 5],
              y=[1, 6, 3, 6, 1],
              mode="lines",
              name="Team A",
              text=["A-1", "A-2", "A-3", "A-4", "A-5"])

t2 = scatter(;x=[1, 2, 3, 4, 5],
             y=[10, 60, 30, 60, 10],
             mode="lines",
             name="Team B",
             text=["B-1", "B-2", "B-3", "B-4", "B-5"])

layout = Layout(;title="Data Labels Hover",
                 xaxis_range=[0, 10],
                 yaxis_range=[0, 100])

data = [t1, t2]

PlotlyJS.plot(data, layout)

I think I'd recommend using Plots.jl for local plotting, though (which can use PlotlyJS.jl). Presumably Plotly.jl is for plotting to the cloud?


问:
Where can I find the checkout page form field in Magento 2.0.1?
I am very new in Magento.

Now I have website where I want to change the form field position from the checkout page form. Here is the screenshot:

Here you can see the location of each section but I can't find the form field to that location. I want to move the country before the city field.

How can I do this?

答:
you can edit on the lay out file of one page checkout "checkout_index_index.xml "
Please checko out this ref : -

Go To


问:
How to extract apple's 1 billion countdown?
I've been trying to figure it out for hours and i didn't success, This Counter from Apple 1 billion downloads prize. doesn't use flash at all, only javascript and 0-9 images, which makes it really cool. Now after stackoverflow successed to extract google's pacman, can we do that?

P.S I can't even know if this is using prototype or scriptaculous since they're both included.

答:
Here it is: http://images.apple.com/global/scripts/downloadcounter.js

```<code>StepTimingFunction = {
    timingFunctionForStepCount: function (a) {
        return function (b) {
            return ((b * (a - 1)) >> 0) / ((a - 1))
        }
    }
};
DownloadCounter = Class.create();
Object.extend(DownloadCounter.prototype, {
    initialize: function (a) {
        this._url = a;
        this.loadData();
        this._isCounting = true
    },
    setIsCounting: function (a) {
        this._isCounting = a
    },
    stop: function () {
        if (this._isCounting) {
            if (this._drawTimeout) {
                window.clearTimeout(this._drawTimeout)
            }
            this.setIsCounting(false);
            if (this._delegate && typeof this._delegate.counterDidStop === "function") {
                this._delegate.counterDidStop(this)
            }
        }
    },
    start: function () {
        if (!this._isCounting) {
            this.loadData();
            this.setIsCounting(true);
            if (this._delegate && typeof this._delegate.counterDidStart === "function") {
                this._delegate.counterDidStart(this)
            }
        }
    },
    isCounting: function () {
        return this._isCounting
    },
    _delegate: null,
    setDelegate: function (a) {
        this._delegate = a
    },
    delegate: function () {
        return this._delegate
    },
    loadData: function () {
        if (this._nextUpdateTimeout) {
            window.clearTimeout(this._nextUpdateTimeout);
            this._nextUpdateTimeout = null
        }
        var a = document.location.href.toString();
        a = a.replace(/.apple.com\/.*$/, ".apple.com");
        new Ajax.Request((a + this._url + "?r=" + Math.random()), {
            method: "get",
            onSuccess: this.dataRequestDidFinishLoading.bind(this)
        })
    },
    dataRequestDidFinishLoading: function (o) {
        var k = o.responseText.split("|"),
            n, d, j, g, l, h, b, f, e, m, a, i, c;
        localServerBasedReferenceTime = Date.parse(o.getResponseHeader("Date"));
        if (k.length === 3) {
            n = k[0].split(" ");
            d = n[1];
            date = n[0].split("-");
            this.setRate(parseInt(k[2]) / 3600000);
            l = date[0];
            g = date[1];
            j = date[2];
            a = Date.parse(g + " " + l + ", " + j + " " + d + " GMT-0700");
            e = new Date(a + 3600000);
            m = e.getTime() - a + 1000;
            this._nextUpdateTimeout = setTimeout(this.loadData.bind(this), m);
            if (typeof localServerBasedReferenceTime === "number") {
                this._lastReferenceTime = localServerBasedReferenceTime
            } else {
                b = new Date();
                this._lastReferenceTime = b.getTime()
            }
            f = this._lastReferenceTime - a;
            i = Math.floor(parseInt(k[1]) + f * (this._rate));
            this.setCurrentCount(i);
            this.setNeedsDisplayIfNeeded()
        }
    },
    setNeedsDisplayIfNeeded: function () {
        if (!this._drawTimeout) {
            this._drawTimeout = setTimeout(this.draw.bind(this), this._drawRefreshRate)
        }
    },
    setElement: function (c) {
        this._element = c;
        var b = this._element.getElementsByClassName("digitGroupSeparator");
        if (b.length > 0) {
            var a = b[0];
            this._element.removeChild(a);
            this.setDigitGroupSeparatorTemplateElement(a)
        }
        this._element.empty();
        this.createDigitElementsIfNeeded();
        this.setNeedsDisplayIfNeeded()
    },
    setDigitGroupSeparatorTemplateElement: function (a) {
        this._digitGroupSeparatorTemplateElement = a
    },
    _currentCount: 0,
    setCurrentCount: function (a) {
        if (a !== this._currentCount) {
            this._currentCount = a;
            this.createDigitElementsIfNeeded()
        }
    },
    digitTemplateElement: function () {
        if (!this._digitTemplateElement) {
            this._digitTemplateElement = document.createElement("span");
            $(this._digitTemplateElement).addClassName("digit");
            var a = document.createElement("div"),
                b = document.createElement("div"),
                c = document.createElement("div");
            $(a).addClassName("digitText");
            $(b).addClassName("digitImage");
            this._digitTemplateElement.appendChild(a);
            this._digitTemplateElement.appendChild(b);
            $(c).addClassName("digitImageElement");
            b.appendChild(c.cloneNode(true));
            b.appendChild(c)
        }
        return this._digitTemplateElement
    },
    createDigitElementsIfNeeded: function () {
        if (this._element && (!this._digitElements || this._digitElements.length !== this._currentCount.toString().length)) {
            this._element.empty();
            this._createDigitElements()
        }
    },
    _createDigitElements: function () {
        if (!this._digitElements) {
            this._digitElements = []
        }
        var e = 0,
            b = (this._maxCount && this._currentCount >= this._maxCount) ? this._maxCount.toString().length : this._currentCount.toString().length,
            c = document.createDocumentFragment(),
            a, h = this.digitTemplateElement(),
            g = this._digitGroupSeparatorTemplateElement,
            d = (this._maxCount && this._currentCount >= this._maxCount) ? String(this._maxCount) : String(this._currentCount),
            f;
        if (!g) {
            g = document.createElement("span");
            $(g).addClassName("digitGroupSeparator")
        }
        for (e = 0 + this._digitElements.length; e < b; e++) {
            a = h.cloneNode(true);
            f = parseInt(d.charAt(b - (e + 1)));
            a.lastChild.style.top = "-" + (f * (this._digitImageAnimationCount * this._digitImageHeight)) + "px";
            this._digitElements[e] = a;
            if (e > 0 && ((e) % 3 == 0)) {
                c.insertBefore(g.cloneNode(true), c.firstChild)
            }
            c.insertBefore(a, c.firstChild)
        }
        this._element.insertBefore(c, this._element.firstChild)
    },
    currentCount: function () {
        return this._currentCount
    },
    setRate: function (a) {
        this._rate = a
    },
    rate: function () {
        return this._rate
    },
    _drawRefreshRate: 50,
    _digitImageHeight: 38,
    setDigitImageHeight: function (a) {
        this._digitImageHeight = a
    },
    _digitImageAnimationCount: 6,
    setDigitImageAnimationCount: function (a) {
        this._digitImageAnimationCount = a
    },
    _maxCount: false,
    setMaxCount: function (a) {
        this._maxCount = a
    },
    draw: function () {
        window.clearTimeout(this._drawTimeout);
        this._drawTimeout = null;
        var h = this._drawRefreshRate,
            e, j, k, c, a, l, o, b, n, d, m, p = this._digitImageHeight * this._digitImageAnimationCount,
            g, f = this._digitElements,
            q;
        if (this._element) {
            m = String(this._currentCount);
            this._currentCount = this._currentCount + Math.floor(this._rate * h);
            if (this._delegate && typeof this._delegate.counterDidReachValue === "function") {
                this._delegate.counterDidReachValue(this, this._currentCount)
            }
            if (this._maxCount && this._currentCount >= this._maxCount) {
                this._isCounting = false
            }
            if (!this._isCounting) {
                return
            }
            e = (this._maxCount && this._currentCount >= this._maxCount) ? String(this._maxCount) : String(this._currentCount);
            j = e.length;
            k = j - 1;
            for (c = k; c >= 0; c--) {
                l = parseInt(e.charAt(c));
                o = parseInt(m.charAt(c));
                if (l !== o) {
                    if (!((k - c) < f.length)) {
                        this._createDigitElements()
                    }
                    a = f[k - c].lastChild;
                    if (a.___animating !== true) {
                        n = o * p;
                        if (l > o) {
                            b = l * p
                        } else {
                            b = (o + (10 - o) + l) * p
                        }
                        if (a.style.top !== (d = "-" + n + "px")) {
                            a.style.top = d
                        }
                        g = 1 + ((b - n) / this._digitImageHeight);
                        a.___animating = true;
                        q = new Effect.Move(a, {
                            x: 0,
                            y: (-1 * b),
                            duration: 0.4,
                            mode: "absolute",
                            transition: StepTimingFunction.timingFunctionForStepCount(g)
                        });
                        q.__element = a;
                        q.finish = function (i) {
                            if (window.removeEventListener) {
                                window.removeEventListener("unload", arguments.callee, false)
                            }
                            if (this.__element !== undefined) {
                                this.__element.___animating = false
                            }
                        };
                        if (window.addEventListener) {
                            window.addEventListener("unload", q.finish, false)
                        }
                    }
                }
            }
        }
        this._lastReferenceTime = (this._lastReferenceTime + h);
        this.setNeedsDisplayIfNeeded()
    }
});
</code>```

ContentLicense: CC BY-SA 2.5

Body:
Here it is: http://images.apple.com/global/scripts/downloadcounter.js

StepTimingFunction = {
    timingFunctionForStepCount: function (a) {
        return function (b) {
            return ((b * (a - 1)) >> 0) / ((a - 1))
        }
    }
};
DownloadCounter = Class.create();
Object.extend(DownloadCounter.prototype, {
    initialize: function (a) {
        this._url = a;
        this.loadData();
        this._isCounting = true
    },
    setIsCounting: function (a) {
        this._isCounting = a
    },
    stop: function () {
        if (this._isCounting) {
            if (this._drawTimeout) {
                window.clearTimeout(this._drawTimeout)
            }
            this.setIsCounting(false);
            if (this._delegate && typeof this._delegate.counterDidStop === "function") {
                this._delegate.counterDidStop(this)
            }
        }
    },
    start: function () {
        if (!this._isCounting) {
            this.loadData();
            this.setIsCounting(true);
            if (this._delegate && typeof this._delegate.counterDidStart === "function") {
                this._delegate.counterDidStart(this)
            }
        }
    },
    isCounting: function () {
        return this._isCounting
    },
    _delegate: null,
    setDelegate: function (a) {
        this._delegate = a
    },
    delegate: function () {
        return this._delegate
    },
    loadData: function () {
        if (this._nextUpdateTimeout) {
            window.clearTimeout(this._nextUpdateTimeout);
            this._nextUpdateTimeout = null
        }
        var a = document.location.href.toString();
        a = a.replace(/.apple.com\/.*$/, ".apple.com");
        new Ajax.Request((a + this._url + "?r=" + Math.random()), {
            method: "get",
            onSuccess: this.dataRequestDidFinishLoading.bind(this)
        })
    },
    dataRequestDidFinishLoading: function (o) {
        var k = o.responseText.split("|"),
            n, d, j, g, l, h, b, f, e, m, a, i, c;
        localServerBasedReferenceTime = Date.parse(o.getResponseHeader("Date"));
        if (k.length === 3) {
            n = k[0].split(" ");
            d = n[1];
            date = n[0].split("-");
            this.setRate(parseInt(k[2]) / 3600000);
            l = date[0];
            g = date[1];
            j = date[2];
            a = Date.parse(g + " " + l + ", " + j + " " + d + " GMT-0700");
            e = new Date(a + 3600000);
            m = e.getTime() - a + 1000;
            this._nextUpdateTimeout = setTimeout(this.loadData.bind(this), m);
            if (typeof localServerBasedReferenceTime === "number") {
                this._lastReferenceTime = localServerBasedReferenceTime
            } else {
                b = new Date();
                this._lastReferenceTime = b.getTime()
            }
            f = this._lastReferenceTime - a;
            i = Math.floor(parseInt(k[1]) + f * (this._rate));
            this.setCurrentCount(i);
            this.setNeedsDisplayIfNeeded()
        }
    },
    setNeedsDisplayIfNeeded: function () {
        if (!this._drawTimeout) {
            this._drawTimeout = setTimeout(this.draw.bind(this), this._drawRefreshRate)
        }
    },
    setElement: function (c) {
        this._element = c;
        var b = this._element.getElementsByClassName("digitGroupSeparator");
        if (b.length > 0) {
            var a = b[0];
            this._element.removeChild(a);
            this.setDigitGroupSeparatorTemplateElement(a)
        }
        this._element.empty();
        this.createDigitElementsIfNeeded();
        this.setNeedsDisplayIfNeeded()
    },
    setDigitGroupSeparatorTemplateElement: function (a) {
        this._digitGroupSeparatorTemplateElement = a
    },
    _currentCount: 0,
    setCurrentCount: function (a) {
        if (a !== this._currentCount) {
            this._currentCount = a;
            this.createDigitElementsIfNeeded()
        }
    },
    digitTemplateElement: function () {
        if (!this._digitTemplateElement) {
            this._digitTemplateElement = document.createElement("span");
            $(this._digitTemplateElement).addClassName("digit");
            var a = document.createElement("div"),
                b = document.createElement("div"),
                c = document.createElement("div");
            $(a).addClassName("digitText");
            $(b).addClassName("digitImage");
            this._digitTemplateElement.appendChild(a);
            this._digitTemplateElement.appendChild(b);
            $(c).addClassName("digitImageElement");
            b.appendChild(c.cloneNode(true));
            b.appendChild(c)
        }
        return this._digitTemplateElement
    },
    createDigitElementsIfNeeded: function () {
        if (this._element && (!this._digitElements || this._digitElements.length !== this._currentCount.toString().length)) {
            this._element.empty();
            this._createDigitElements()
        }
    },
    _createDigitElements: function () {
        if (!this._digitElements) {
            this._digitElements = []
        }
        var e = 0,
            b = (this._maxCount && this._currentCount >= this._maxCount) ? this._maxCount.toString().length : this._currentCount.toString().length,
            c = document.createDocumentFragment(),
            a, h = this.digitTemplateElement(),
            g = this._digitGroupSeparatorTemplateElement,
            d = (this._maxCount && this._currentCount >= this._maxCount) ? String(this._maxCount) : String(this._currentCount),
            f;
        if (!g) {
            g = document.createElement("span");
            $(g).addClassName("digitGroupSeparator")
        }
        for (e = 0 + this._digitElements.length; e < b; e++) {
            a = h.cloneNode(true);
            f = parseInt(d.charAt(b - (e + 1)));
            a.lastChild.style.top = "-" + (f * (this._digitImageAnimationCount * this._digitImageHeight)) + "px";
            this._digitElements[e] = a;
            if (e > 0 && ((e) % 3 == 0)) {
                c.insertBefore(g.cloneNode(true), c.firstChild)
            }
            c.insertBefore(a, c.firstChild)
        }
        this._element.insertBefore(c, this._element.firstChild)
    },
    currentCount: function () {
        return this._currentCount
    },
    setRate: function (a) {
        this._rate = a
    },
    rate: function () {
        return this._rate
    },
    _drawRefreshRate: 50,
    _digitImageHeight: 38,
    setDigitImageHeight: function (a) {
        this._digitImageHeight = a
    },
    _digitImageAnimationCount: 6,
    setDigitImageAnimationCount: function (a) {
        this._digitImageAnimationCount = a
    },
    _maxCount: false,
    setMaxCount: function (a) {
        this._maxCount = a
    },
    draw: function () {
        window.clearTimeout(this._drawTimeout);
        this._drawTimeout = null;
        var h = this._drawRefreshRate,
            e, j, k, c, a, l, o, b, n, d, m, p = this._digitImageHeight * this._digitImageAnimationCount,
            g, f = this._digitElements,
            q;
        if (this._element) {
            m = String(this._currentCount);
            this._currentCount = this._currentCount + Math.floor(this._rate * h);
            if (this._delegate && typeof this._delegate.counterDidReachValue === "function") {
                this._delegate.counterDidReachValue(this, this._currentCount)
            }
            if (this._maxCount && this._currentCount >= this._maxCount) {
                this._isCounting = false
            }
            if (!this._isCounting) {
                return
            }
            e = (this._maxCount && this._currentCount >= this._maxCount) ? String(this._maxCount) : String(this._currentCount);
            j = e.length;
            k = j - 1;
            for (c = k; c >= 0; c--) {
                l = parseInt(e.charAt(c));
                o = parseInt(m.charAt(c));
                if (l !== o) {
                    if (!((k - c) < f.length)) {
                        this._createDigitElements()
                    }
                    a = f[k - c].lastChild;
                    if (a.___animating !== true) {
                        n = o * p;
                        if (l > o) {
                            b = l * p
                        } else {
                            b = (o + (10 - o) + l) * p
                        }
                        if (a.style.top !== (d = "-" + n + "px")) {
                            a.style.top = d
                        }
                        g = 1 + ((b - n) / this._digitImageHeight);
                        a.___animating = true;
                        q = new Effect.Move(a, {
                            x: 0,
                            y: (-1 * b),
                            duration: 0.4,
                            mode: "absolute",
                            transition: StepTimingFunction.timingFunctionForStepCount(g)
                        });
                        q.__element = a;
                        q.finish = function (i) {
                            if (window.removeEventListener) {
                                window.removeEventListener("unload", arguments.callee, false)
                            }
                            if (this.__element !== undefined) {
                                this.__element.___animating = false
                            }
                        };
                        if (window.addEventListener) {
                            window.addEventListener("unload", q.finish, false)
                        }
                    }
                }
            }
        }
        this._lastReferenceTime = (this._lastReferenceTime + h);
        this.setNeedsDisplayIfNeeded()
    }
});


问:
Group Distinct Values and Counts for Each Property in One Query
I have a data in profile collection

```<code>[
    {
        name: "Harish",
        gender: "Male",
        caste: "Vokkaliga",
        education: "B.E"
    },
    {
        name: "Reshma",
        gender: "Female",
        caste: "Vokkaliga",
        education: "B.E"
    },
    {
        name: "Rangnath",
        gender: "Male",
        caste: "Lingayath",
        education: "M.C.A"
    },
    {
        name: "Lakshman",
        gender: "Male",
        caste: "Lingayath",
        education: "B.Com"
    },
    {
        name: "Reshma",
        gender: "Female",
        caste: "Lingayath",
        education: "B.E"
    }
]
</code>```

here I need to calculate total Number of different gender, total number of different caste and total number of different education.
Expected o/p

```<code>{
    gender: [{
        name: "Male",
        total: "3"
    },
    {
        name: "Female",
        total: "2"
    }],
    caste: [{
        name: "Vokkaliga",
        total: "2"
    },
    {
        name: "Lingayath",
        total: "3"
    }],
    education: [{
        name: "B.E",
        total: "3"
    },
    {
        name: "M.C.A",
        total: "1"
    },
    {
        name: "B.Com",
        total: "1"
    }]
}
</code>```

using mongodb aggregation how can I get the expected result.

答:
There are different approaches depending on the version available, but they all essentially break down to transforming your document fields into separate documents in an "array", then "unwinding" that array with $unwind and doing successive $group stages in order to accumulate the output totals and arrays.

MongoDB 3.4.4 and above

Latest releases have special operators like $arrayToObject and $objectToArray which can make transfer to the initial "array" from the source document more dynamic than in earlier releases:

```<code>db.profile.aggregate([
  { "$project": {
     "_id": 0,
     "data": {
       "$filter": {
         "input": { "$objectToArray": "$$ROOT" },
         "cond": { "$in": [ "$$this.k", ["gender","caste","education"] ] }
       }
     }
  }},
  { "$unwind": "$data" },
  { "$group": {
    "_id": "$data",
    "total": { "$sum": 1 }
  }},
  { "$group": {
    "_id": "$_id.k",
    "v": {
      "$push": { "name": "$_id.v", "total": "$total" }
    }
  }},
  { "$group": {
    "_id": null,
    "data": { "$push": { "k": "$_id", "v": "$v" } }
  }},
  { "$replaceRoot": {
    "newRoot": {
      "$arrayToObject": "$data"
    }
  }}
])
</code>```

So using $objectToArray you make the initial document into an array of it's keys and values as "k" and "v" keys in the resulting array of objects. We apply $filter here in order to select by "key". Here using $in with a list of keys we want, but this could be more dynamically used as a list of keys to "exclude" where that was shorter. It's just using logical operators to evaluate the condition.

The end stage here uses $replaceRoot and since all our manipulation and "grouping" in between still keeps that "k" and "v" form, we then use $arrayToObject here to promote our "array of objects" in result to the "keys" of the top level document in output.

MongoDB 3.6 $mergeObjects

As an extra wrinkle here, MongoDB 3.6 includes $mergeObjects which can be used as an "accumulator" in a $group pipeline stage as well, thus replacing the $push and making the final $replaceRoot simply shifting the "data" key to the "root" of the returned document instead:

```<code>db.profile.aggregate([
  { "$project": {
     "_id": 0,
     "data": {
       "$filter": {
         "input": { "$objectToArray": "$$ROOT" },
         "cond": { "$in": [ "$$this.k", ["gender","caste","education"] ] }
       }
     }
  }},
  { "$unwind": "$data" },
  { "$group": { "_id": "$data", "total": { "$sum": 1 } }},
  { "$group": {
    "_id": "$_id.k",
    "v": {
      "$push": { "name": "$_id.v", "total": "$total" }
    }
  }},
  { "$group": {
    "_id": null,
    "data": {
      "$mergeObjects": {
        "$arrayToObject": [
          [{ "k": "$_id", "v": "$v" }]
        ]
      }
    }
  }},
  { "$replaceRoot": { "newRoot": "$data"  } }
])
</code>```

This is not really that different to what is being demonstrated overall, but simply demonstrates how $mergeObjects can be used in this way and may be useful in cases where the grouping key was something different and we did not want that final "merge" to the root space of the object.

Note that the $arrayToObject is still needed to transform the "value" back into the name of the "key", but we just do it during the accumulation rather than after the grouping, since the new accumulation allows the "merge" of keys.

MongoDB 3.2

Taking it back a version or even if you have a MongoDB 3.4.x that is less than the 3.4.4 release, we can still use much of this but instead we deal with the creation of the array in a more static fashion, as well as handling the final "transform" on output differently due to the aggregation operators we don't have:

```<code>db.profile.aggregate([
  { "$project": {
    "data": [
      { "k": "gender", "v": "$gender" },
      { "k": "caste", "v": "$caste" },
      { "k": "education", "v": "$education" }
    ]
  }},
  { "$unwind": "$data" },
  { "$group": {
    "_id": "$data",
    "total": { "$sum": 1 }
  }},
  { "$group": {
    "_id": "$_id.k",
    "v": {
      "$push": { "name": "$_id.v", "total": "$total" }
    }
  }},
  { "$group": {
    "_id": null,
    "data": { "$push": { "k": "$_id", "v": "$v" } }
  }},
  /*
  { "$replaceRoot": {
    "newRoot": {
      "$arrayToObject": "$data"
    }
  }}
  */
]).map( d =>
  d.data.map( e => ({ [e.k]: e.v }) )
    .reduce((acc,curr) => Object.assign(acc,curr),{})
)
</code>```

This is exactly the same thing, except instead of having a dynamic transform of the document into the array, we actually "explicitly" assign each array member with the same "k" and "v" notation. Really just keeping those key names for convention at this point since none of the aggregation operators here depend on that at all.

Also instead of using $replaceRoot, we just do exactly the same thing as what the previous pipeline stage implementation was doing there but in client code instead. All MongoDB drivers have some implementation of cursor.map() to enable "cursor transforms". Here with the shell we use the basic JavaScript functions of Array.map() and Array.reduce() to take that output and again promote the array content to being the keys of the top level document returned.

MongoDB 2.6

And falling back to MongoDB 2.6 to cover the versions in between, the only thing that changes here is the usage of $map and a $literal for input with the array declaration:

```<code>db.profile.aggregate([
  { "$project": {
    "data": {
      "$map": {
        "input": { "$literal": ["gender","caste", "education"] },
        "as": "k",
        "in": {
          "k": "$$k",
          "v": {
            "$cond": {
              "if": { "$eq": [ "$$k", "gender" ] },
              "then": "$gender",
              "else": {
                "$cond": {
                  "if": { "$eq": [ "$$k", "caste" ] },
                  "then": "$caste",
                  "else": "$education"
                }
              }
            }
          }
        }
      }
    }
  }},
  { "$unwind": "$data" },
  { "$group": {
    "_id": "$data",
    "total": { "$sum": 1 }
  }},
  { "$group": {
    "_id": "$_id.k",
    "v": {
      "$push": { "name": "$_id.v", "total": "$total" }
    }
  }},
  { "$group": {
    "_id": null,
    "data": { "$push": { "k": "$_id", "v": "$v" } }
  }},
  /*
  { "$replaceRoot": {
    "newRoot": {
      "$arrayToObject": "$data"
    }
  }}
  */
])
.map( d =>
  d.data.map( e => ({ [e.k]: e.v }) )
    .reduce((acc,curr) => Object.assign(acc,curr),{})
)
</code>```

Since the basic idea here is to "iterate" a provided array of the field names, the actual assignment of values comes by "nesting" the $cond statements. For three possible outcomes this means only a single nesting in order to "branch" for each outcome.

Modern MongoDB from 3.4 have $switch which makes this branching simpler, yet this demonstrates the logic was always possible and the $cond operator has been around since the aggregation framework was introduced in MongoDB 2.2.

Again, the same transformation on the cursor result applies as there is nothing new there and most programming languages have the ability to do this for years, if not from inception.

Of course the basic process can even be done way back to MongoDB 2.2, but just applying the array creation and $unwind in a different way. But no-one should be running any MongoDB under 2.8 at this point in time, and official support even from 3.0 is even fast running out.

Output

For visualization, the output of all demonstrated pipelines here has the following form before the last "transform" is done:

```<code>/* 1 */
{
    "_id" : null,
    "data" : [
        {
            "k" : "gender",
            "v" : [
                {
                    "name" : "Male",
                    "total" : 3.0
                },
                {
                    "name" : "Female",
                    "total" : 2.0
                }
            ]
        },
        {
            "k" : "education",
            "v" : [
                {
                    "name" : "M.C.A",
                    "total" : 1.0
                },
                {
                    "name" : "B.E",
                    "total" : 3.0
                },
                {
                    "name" : "B.Com",
                    "total" : 1.0
                }
            ]
        },
        {
            "k" : "caste",
            "v" : [
                {
                    "name" : "Lingayath",
                    "total" : 3.0
                },
                {
                    "name" : "Vokkaliga",
                    "total" : 2.0
                }
            ]
        }
    ]
}
</code>```

And then either by the $replaceRoot or the cursor transform as demonstrated the result becomes:

```<code>/* 1 */
{
    "gender" : [
        {
            "name" : "Male",
            "total" : 3.0
        },
        {
            "name" : "Female",
            "total" : 2.0
        }
    ],
    "education" : [
        {
            "name" : "M.C.A",
            "total" : 1.0
        },
        {
            "name" : "B.E",
            "total" : 3.0
        },
        {
            "name" : "B.Com",
            "total" : 1.0
        }
    ],
    "caste" : [
        {
            "name" : "Lingayath",
            "total" : 3.0
        },
        {
            "name" : "Vokkaliga",
            "total" : 2.0
        }
    ]
}
</code>```

So whilst we can put some new and fancy operators into the aggregation pipeline where we have those available, the most common use case is in these "end of pipeline transforms" in which case we may as well simply do the same transformation on each document in the cursor results returned instead.

Body:
I have a data in profile collection

[
    {
        name: "Harish",
        gender: "Male",
        caste: "Vokkaliga",
        education: "B.E"
    },
    {
        name: "Reshma",
        gender: "Female",
        caste: "Vokkaliga",
        education: "B.E"
    },
    {
        name: "Rangnath",
        gender: "Male",
        caste: "Lingayath",
        education: "M.C.A"
    },
    {
        name: "Lakshman",
        gender: "Male",
        caste: "Lingayath",
        education: "B.Com"
    },
    {
        name: "Reshma",
        gender: "Female",
        caste: "Lingayath",
        education: "B.E"
    }
]

here I need to calculate total Number of different gender, total number of different caste and total number of different education.
Expected o/p

{
    gender: [{
        name: "Male",
        total: "3"
    },
    {
        name: "Female",
        total: "2"
    }],
    caste: [{
        name: "Vokkaliga",
        total: "2"
    },
    {
        name: "Lingayath",
        total: "3"
    }],
    education: [{
        name: "B.E",
        total: "3"
    },
    {
        name: "M.C.A",
        total: "1"
    },
    {
        name: "B.Com",
        total: "1"
    }]
}

using mongodb aggregation how can I get the expected result.

Body:
There are different approaches depending on the version available, but they all essentially break down to transforming your document fields into separate documents in an "array", then "unwinding" that array with $unwind and doing successive $group stages in order to accumulate the output totals and arrays.

MongoDB 3.4.4 and above

Latest releases have special operators like $arrayToObject and $objectToArray which can make transfer to the initial "array" from the source document more dynamic than in earlier releases:

db.profile.aggregate([
  { "$project": {
     "_id": 0,
     "data": {
       "$filter": {
         "input": { "$objectToArray": "$$ROOT" },
         "cond": { "$in": [ "$$this.k", ["gender","caste","education"] ] }
       }
     }
  }},
  { "$unwind": "$data" },
  { "$group": {
    "_id": "$data",
    "total": { "$sum": 1 }
  }},
  { "$group": {
    "_id": "$_id.k",
    "v": {
      "$push": { "name": "$_id.v", "total": "$total" }
    }
  }},
  { "$group": {
    "_id": null,
    "data": { "$push": { "k": "$_id", "v": "$v" } }
  }},
  { "$replaceRoot": {
    "newRoot": {
      "$arrayToObject": "$data"
    }
  }}
])

So using $objectToArray you make the initial document into an array of it's keys and values as "k" and "v" keys in the resulting array of objects. We apply $filter here in order to select by "key". Here using $in with a list of keys we want, but this could be more dynamically used as a list of keys to "exclude" where that was shorter. It's just using logical operators to evaluate the condition.

The end stage here uses $replaceRoot and since all our manipulation and "grouping" in between still keeps that "k" and "v" form, we then use $arrayToObject here to promote our "array of objects" in result to the "keys" of the top level document in output.

MongoDB 3.6 $mergeObjects

As an extra wrinkle here, MongoDB 3.6 includes $mergeObjects which can be used as an "accumulator" in a $group pipeline stage as well, thus replacing the $push and making the final $replaceRoot simply shifting the "data" key to the "root" of the returned document instead:

db.profile.aggregate([
  { "$project": {
     "_id": 0,
     "data": {
       "$filter": {
         "input": { "$objectToArray": "$$ROOT" },
         "cond": { "$in": [ "$$this.k", ["gender","caste","education"] ] }
       }
     }
  }},
  { "$unwind": "$data" },
  { "$group": { "_id": "$data", "total": { "$sum": 1 } }},
  { "$group": {
    "_id": "$_id.k",
    "v": {
      "$push": { "name": "$_id.v", "total": "$total" }
    }
  }},
  { "$group": {
    "_id": null,
    "data": {
      "$mergeObjects": {
        "$arrayToObject": [
          [{ "k": "$_id", "v": "$v" }]
        ]
      }
    }
  }},
  { "$replaceRoot": { "newRoot": "$data"  } }
])

This is not really that different to what is being demonstrated overall, but simply demonstrates how $mergeObjects can be used in this way and may be useful in cases where the grouping key was something different and we did not want that final "merge" to the root space of the object.

Note that the $arrayToObject is still needed to transform the "value" back into the name of the "key", but we just do it during the accumulation rather than after the grouping, since the new accumulation allows the "merge" of keys.

MongoDB 3.2

Taking it back a version or even if you have a MongoDB 3.4.x that is less than the 3.4.4 release, we can still use much of this but instead we deal with the creation of the array in a more static fashion, as well as handling the final "transform" on output differently due to the aggregation operators we don't have:

db.profile.aggregate([
  { "$project": {
    "data": [
      { "k": "gender", "v": "$gender" },
      { "k": "caste", "v": "$caste" },
      { "k": "education", "v": "$education" }
    ]
  }},
  { "$unwind": "$data" },
  { "$group": {
    "_id": "$data",
    "total": { "$sum": 1 }
  }},
  { "$group": {
    "_id": "$_id.k",
    "v": {
      "$push": { "name": "$_id.v", "total": "$total" }
    }
  }},
  { "$group": {
    "_id": null,
    "data": { "$push": { "k": "$_id", "v": "$v" } }
  }},
  /*
  { "$replaceRoot": {
    "newRoot": {
      "$arrayToObject": "$data"
    }
  }}
  */
]).map( d =>
  d.data.map( e => ({ [e.k]: e.v }) )
    .reduce((acc,curr) => Object.assign(acc,curr),{})
)

This is exactly the same thing, except instead of having a dynamic transform of the document into the array, we actually "explicitly" assign each array member with the same "k" and "v" notation. Really just keeping those key names for convention at this point since none of the aggregation operators here depend on that at all.

Also instead of using $replaceRoot, we just do exactly the same thing as what the previous pipeline stage implementation was doing there but in client code instead. All MongoDB drivers have some implementation of cursor.map() to enable "cursor transforms". Here with the shell we use the basic JavaScript functions of Array.map() and Array.reduce() to take that output and again promote the array content to being the keys of the top level document returned.

MongoDB 2.6

And falling back to MongoDB 2.6 to cover the versions in between, the only thing that changes here is the usage of $map and a $literal for input with the array declaration:

db.profile.aggregate([
  { "$project": {
    "data": {
      "$map": {
        "input": { "$literal": ["gender","caste", "education"] },
        "as": "k",
        "in": {
          "k": "$$k",
          "v": {
            "$cond": {
              "if": { "$eq": [ "$$k", "gender" ] },
              "then": "$gender",
              "else": {
                "$cond": {
                  "if": { "$eq": [ "$$k", "caste" ] },
                  "then": "$caste",
                  "else": "$education"
                }
              }
            }
          }
        }
      }
    }
  }},
  { "$unwind": "$data" },
  { "$group": {
    "_id": "$data",
    "total": { "$sum": 1 }
  }},
  { "$group": {
    "_id": "$_id.k",
    "v": {
      "$push": { "name": "$_id.v", "total": "$total" }
    }
  }},
  { "$group": {
    "_id": null,
    "data": { "$push": { "k": "$_id", "v": "$v" } }
  }},
  /*
  { "$replaceRoot": {
    "newRoot": {
      "$arrayToObject": "$data"
    }
  }}
  */
])
.map( d =>
  d.data.map( e => ({ [e.k]: e.v }) )
    .reduce((acc,curr) => Object.assign(acc,curr),{})
)

Since the basic idea here is to "iterate" a provided array of the field names, the actual assignment of values comes by "nesting" the $cond statements. For three possible outcomes this means only a single nesting in order to "branch" for each outcome.

Modern MongoDB from 3.4 have $switch which makes this branching simpler, yet this demonstrates the logic was always possible and the $cond operator has been around since the aggregation framework was introduced in MongoDB 2.2.

Again, the same transformation on the cursor result applies as there is nothing new there and most programming languages have the ability to do this for years, if not from inception.

Of course the basic process can even be done way back to MongoDB 2.2, but just applying the array creation and $unwind in a different way. But no-one should be running any MongoDB under 2.8 at this point in time, and official support even from 3.0 is even fast running out.

Output

For visualization, the output of all demonstrated pipelines here has the following form before the last "transform" is done:

/* 1 */
{
    "_id" : null,
    "data" : [
        {
            "k" : "gender",
            "v" : [
                {
                    "name" : "Male",
                    "total" : 3.0
                },
                {
                    "name" : "Female",
                    "total" : 2.0
                }
            ]
        },
        {
            "k" : "education",
            "v" : [
                {
                    "name" : "M.C.A",
                    "total" : 1.0
                },
                {
                    "name" : "B.E",
                    "total" : 3.0
                },
                {
                    "name" : "B.Com",
                    "total" : 1.0
                }
            ]
        },
        {
            "k" : "caste",
            "v" : [
                {
                    "name" : "Lingayath",
                    "total" : 3.0
                },
                {
                    "name" : "Vokkaliga",
                    "total" : 2.0
                }
            ]
        }
    ]
}

And then either by the $replaceRoot or the cursor transform as demonstrated the result becomes:

/* 1 */
{
    "gender" : [
        {
            "name" : "Male",
            "total" : 3.0
        },
        {
            "name" : "Female",
            "total" : 2.0
        }
    ],
    "education" : [
        {
            "name" : "M.C.A",
            "total" : 1.0
        },
        {
            "name" : "B.E",
            "total" : 3.0
        },
        {
            "name" : "B.Com",
            "total" : 1.0
        }
    ],
    "caste" : [
        {
            "name" : "Lingayath",
            "total" : 3.0
        },
        {
            "name" : "Vokkaliga",
            "total" : 2.0
        }
    ]
}

So whilst we can put some new and fancy operators into the aggregation pipeline where we have those available, the most common use case is in these "end of pipeline transforms" in which case we may as well simply do the same transformation on each document in the cursor results returned instead.


问:
How to convert an Object {} to an Array [] of key-value pairs in JavaScript
I want to convert an object like this:

```<code>{"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}
</code>```

into an array of key-value pairs like this:

```<code>[[1,5],[2,7],[3,0],[4,0]...].
</code>```

How can I convert an Object to an Array of key-value pairs in JavaScript?

答:
Recursive convert object to array</p>

```<code>function is_object(mixed_var) {
    if (mixed_var instanceof Array) {
        return false;
    } else {
        return (mixed_var !== null) && (typeof( mixed_var ) == 'object');
    }
}

function objectToArray(obj) {
    var array = [], tempObject;
    for (var key in obj) {

        tempObject = obj[key];

        if (is_object(obj[key])) {
            tempObject = objectToArray(obj[key]);
        }
        array[key] = tempObject;
    }
    return array;
}
</code>```

Body:
I want to convert an object like this:

{"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}

into an array of key-value pairs like this:

[[1,5],[2,7],[3,0],[4,0]...].

How can I convert an Object to an Array of key-value pairs in JavaScript?

Body:
Recursive convert object to array

function is_object(mixed_var) {
    if (mixed_var instanceof Array) {
        return false;
    } else {
        return (mixed_var !== null) && (typeof( mixed_var ) == 'object');
    }
}

function objectToArray(obj) {
    var array = [], tempObject;
    for (var key in obj) {

        tempObject = obj[key];

        if (is_object(obj[key])) {
            tempObject = objectToArray(obj[key]);
        }
        array[key] = tempObject;
    }
    return array;
}


问:
'substring(from:)' is deprecated: Please use String slicing subscript with a 'partial range from' operator. Swift 4 Error
I am converting my existing app from Swift 3 to Swift 4. It is giving the error:

'substring(from:)' is deprecated: Please use String slicing subscript with a 'partial range from' operator.

and

'characters' is deprecated: Please use String or Substring directly

My Swift 3 code is:

```<code>public convenience init?(hexString: String, alpha: Float) {
    var hex = hexString

    // Check for hash and remove the hash
    if hex.hasPrefix("#") {
        hex = hex.substring(from: hex.characters.index(hex.startIndex, offsetBy: 1))
    }

    if (hex.range(of: "(^[0-9A-Fa-f]{6}$)|(^[0-9A-Fa-f]{3}$)", options: .regularExpression) != nil) {

        // Deal with 3 character Hex strings
        if hex.characters.count == 3 {
            let redHex   = hex.substring(to: hex.characters.index(hex.startIndex, offsetBy: 1))
            let greenHex = hex.substring(with: (hex.characters.index(hex.startIndex, offsetBy: 1) ..< hex.characters.index(hex.startIndex, offsetBy: 2)))
            let blueHex  = hex.substring(from: hex.characters.index(hex.startIndex, offsetBy: 2))

            hex = redHex + redHex + greenHex + greenHex + blueHex + blueHex
        }

        let redHex = hex.substring(to: hex.characters.index(hex.startIndex, offsetBy: 2))
        let greenHex = hex.substring(with: (hex.characters.index(hex.startIndex, offsetBy: 2) ..< hex.characters.index(hex.startIndex, offsetBy: 4)))
        let blueHex = hex.substring(with: (hex.characters.index(hex.startIndex, offsetBy: 4) ..< hex.characters.index(hex.startIndex, offsetBy: 6)))

        var redInt:   CUnsignedInt = 0
        var greenInt: CUnsignedInt = 0
        var blueInt:  CUnsignedInt = 0

        Scanner(string: redHex).scanHexInt32(&redInt)
        Scanner(string: greenHex).scanHexInt32(&greenInt)
        Scanner(string: blueHex).scanHexInt32(&blueInt)

        self.init(red: CGFloat(redInt) / 255.0, green: CGFloat(greenInt) / 255.0, blue: CGFloat(blueInt) / 255.0, alpha: CGFloat(alpha))
    }
    else {
        self.init()
        return nil
    }
}
</code>```

How can I convert it to the Swift 4?

答:
'characters' is deprecated: Please use String or Substring directly

For this you can directly loop through string in swift 4 so there is no need to characters array.

And for

'substring(from:)' is deprecated: Please use String slicing subscript with a 'partial range from' operator.

Refer How can I use String slicing subscripts in Swift 4?

Body:
I am converting my existing app from Swift 3 to Swift 4. It is giving the error:

'substring(from:)' is deprecated: Please use String slicing subscript with a 'partial range from' operator.

and

'characters' is deprecated: Please use String or Substring directly

My Swift 3 code is:

public convenience init?(hexString: String, alpha: Float) {
    var hex = hexString

    // Check for hash and remove the hash
    if hex.hasPrefix("#") {
        hex = hex.substring(from: hex.characters.index(hex.startIndex, offsetBy: 1))
    }

    if (hex.range(of: "(^[0-9A-Fa-f]{6}$)|(^[0-9A-Fa-f]{3}$)", options: .regularExpression) != nil) {

        // Deal with 3 character Hex strings
        if hex.characters.count == 3 {
            let redHex   = hex.substring(to: hex.characters.index(hex.startIndex, offsetBy: 1))
            let greenHex = hex.substring(with: (hex.characters.index(hex.startIndex, offsetBy: 1) ..< hex.characters.index(hex.startIndex, offsetBy: 2)))
            let blueHex  = hex.substring(from: hex.characters.index(hex.startIndex, offsetBy: 2))

            hex = redHex + redHex + greenHex + greenHex + blueHex + blueHex
        }

        let redHex = hex.substring(to: hex.characters.index(hex.startIndex, offsetBy: 2))
        let greenHex = hex.substring(with: (hex.characters.index(hex.startIndex, offsetBy: 2) ..< hex.characters.index(hex.startIndex, offsetBy: 4)))
        let blueHex = hex.substring(with: (hex.characters.index(hex.startIndex, offsetBy: 4) ..< hex.characters.index(hex.startIndex, offsetBy: 6)))

        var redInt:   CUnsignedInt = 0
        var greenInt: CUnsignedInt = 0
        var blueInt:  CUnsignedInt = 0

        Scanner(string: redHex).scanHexInt32(&redInt)
        Scanner(string: greenHex).scanHexInt32(&greenInt)
        Scanner(string: blueHex).scanHexInt32(&blueInt)

        self.init(red: CGFloat(redInt) / 255.0, green: CGFloat(greenInt) / 255.0, blue: CGFloat(blueInt) / 255.0, alpha: CGFloat(alpha))
    }
    else {
        self.init()
        return nil
    }
}

How can I convert it to the Swift 4?


问:
Why is size_type a 32-bit integer on a 64-bit platform?
The std::vector::resize member function is like this:

void resize (size_type n);

Per my understanding, size_type should be a 64-bit long type on a 64-bit platform. But compiling the following program:

```<code>#include <iostream>
#include <climits>
#include <vector>

using namespace std;

vector<char> v;

int main() {
    // your code goes here
    v.resize(INT_MAX +1);
    for (auto i = 0; i < v.size(); i++ ) {
        cout << i << endl;
    }
    return 0;
}
</code>```

The following warning is generated:

```<code>g++ -std=c++11 hello.cpp
hello.cpp: In function ‘int main()’:
hello.cpp:11:19: warning: integer overflow in expression [-Woverflow]
  v.resize(INT_MAX +1);
</code>```

So the size_type is still 32-bit int even though we're working on a  64-bit platform?

答:
The vector's size_type is probably a typedef for allocator::size_t which is (probably) a typedef for std::size_t which is an unsigned type. The generated warning has nothing to do with the vector's resize() signature. You are overflowing the max integer limit and your INT_MAX + 1 expression invokes undefined behaviour. Also the for loop deduces the type of i to be int which will also issue a warning when comparing signed and unsigned values. If you really want to you can cast to size_type and add 1:

```<code>v.resize(static_cast<std::vector<char>::size_type>(INT_MAX) + 1);
</code>```

and append the u literal to initial value inside the for loop:

```<code>for (auto i = 0u; i < v.size(); i++)
</code>```

You can get the underlying type name with:

```<code>std::cout << typeid(std::vector<char>::size_type).name();
</code>```

Body:
The std::vector::resize member function is like this:

void resize (size_type n);

Per my understanding, size_type should be a 64-bit long type on a 64-bit platform. But compiling the following program:

#include <iostream>
#include <climits>
#include <vector>

using namespace std;

vector<char> v;

int main() {
    // your code goes here
    v.resize(INT_MAX +1);
    for (auto i = 0; i < v.size(); i++ ) {
        cout << i << endl;
    }
    return 0;
}

The following warning is generated:

g++ -std=c++11 hello.cpp
hello.cpp: In function ‘int main()’:
hello.cpp:11:19: warning: integer overflow in expression [-Woverflow]
  v.resize(INT_MAX +1);

So the size_type is still 32-bit int even though we're working on a  64-bit platform?

Body:
The vector's size_type is probably a typedef for allocator::size_t which is (probably) a typedef for std::size_t which is an unsigned type. The generated warning has nothing to do with the vector's resize() signature. You are overflowing the max integer limit and your INT_MAX + 1 expression invokes undefined behaviour. Also the for loop deduces the type of i to be int which will also issue a warning when comparing signed and unsigned values. If you really want to you can cast to size_type and add 1:

v.resize(static_cast<std::vector<char>::size_type>(INT_MAX) + 1);

and append the u literal to initial value inside the for loop:

for (auto i = 0u; i < v.size(); i++)

You can get the underlying type name with:

std::cout << typeid(std::vector<char>::size_type).name();


问:
Extending The Controller Class in CodeIgniter
I have class MY_Controller extends CI_Controller and common logic for big profile section, so I'va tried to create class Profile extends MY_Controller with common logic for profile section and all class related to this section should extends this Profile class as I understand right, but when I tried to create class Index extends Profile I recieve an error:

```<code>Fatal error: Class 'Profile' not found
</code>```

CodeIgniter tries to find this class in index.php which I am running.

Where is my mistake? Or maybe there is anoter better way to mark out common logic?

答:
I found this page on Google because I had the same problem. I didn't like the answers listed here so I created my own solution.

1) Place your parent class in the core folder.

2) Place an include statement at the beginning of all classes that include the parent class.

So a typical controller might look like this:

```<code><?php

require_once APPPATH . 'core/Your_Base_Class.php';
// must use require_once instead of include or you will get an error when loading 404 pages

class NormalController extends Your_Base_Class
{
    public function __construct()
    {
        parent::__construct();

        // authentication/permissions code, or whatever you want to put here
    }

    // your methods go here
}
</code>```

The reason I like this solution is, the whole point of creating a parent class is to cut down on code repetition. So I don't like the other answer that suggested copy/pasting the parent class into all of your controller classes.

Body:
I have class MY_Controller extends CI_Controller and common logic for big profile section, so I'va tried to create class Profile extends MY_Controller with common logic for profile section and all class related to this section should extends this Profile class as I understand right, but when I tried to create class Index extends Profile I recieve an error:

Fatal error: Class 'Profile' not found

CodeIgniter tries to find this class in index.php which I am running.

Where is my mistake? Or maybe there is anoter better way to mark out common logic?

Body:
I found this page on Google because I had the same problem. I didn't like the answers listed here so I created my own solution.

1) Place your parent class in the core folder.

2) Place an include statement at the beginning of all classes that include the parent class.

So a typical controller might look like this:

<?php

require_once APPPATH . 'core/Your_Base_Class.php';
// must use require_once instead of include or you will get an error when loading 404 pages

class NormalController extends Your_Base_Class
{
    public function __construct()
    {
        parent::__construct();

        // authentication/permissions code, or whatever you want to put here
    }

    // your methods go here
}

The reason I like this solution is, the whole point of creating a parent class is to cut down on code repetition. So I don't like the other answer that suggested copy/pasting the parent class into all of your controller classes.


问:
How to get data in deeply nested JSON (more than 5 layers)
I use a Teleport API. Their JSON data is heavily nested and I'm struggling to get the relevant data.

The data is as below. I want to get the data in categories.

```<code>{
 "_embedded": {
 "city:search-results": [
  {
    "_embedded": {
      "city:item": {
        "_embedded": {
          "city:urban_area": {
            "_embedded": {
              "ua:scores": {
                "_links": {
                  "self": {
                    "href": "https://api.teleport.org/api/urban_areas/slug:tokyo/scores/"
                  }
                },
                "categories": [
                  {
                    "color": "#f3c32c",
                    "name": "Housing",
                    "score_out_of_10": 5.710999999999999
                  },
                  {
                    "color": "#f3d630",
                    "name": "Cost of Living",
                    "score_out_of_10": 3.343
                  },.....
</code>```

The code.  I use React, Redux and Lodash and I tried to iterate the data by map function.

```<code> let item;
   if(this.props.data) {
          item = _.map(this.props.data._embedded.city:search-results._embedded.city:item._embedded.city:urban_area._embedded.ua:scores.categories,
    /** This nested props doesn't work **/
    data => {
    return (
             <div>
             <h2>{data.name}</h2>
             <p>{data.score_out_of_10}</p>
             </div>
         )
     })
</code>```

Is there a better way to iterate the data in heavily nested JSON data?

答:
Since you mentioned lodash try to use the get utility :

```<code>import _get from 'lodash/get';

    _get(this.props.data, '_embedded.city:search-results._embedded.city:item._embedded.city:urban_area._embedded.ua:scores.categories', ''),
</code>```

To prevent the use of the reserved keyword : when you try to access the data, and this helps also to prevent the app from crashing when the data don't exist.

Body:
I use a Teleport API. Their JSON data is heavily nested and I'm struggling to get the relevant data.

The data is as below. I want to get the data in categories.

{
 "_embedded": {
 "city:search-results": [
  {
    "_embedded": {
      "city:item": {
        "_embedded": {
          "city:urban_area": {
            "_embedded": {
              "ua:scores": {
                "_links": {
                  "self": {
                    "href": "https://api.teleport.org/api/urban_areas/slug:tokyo/scores/"
                  }
                },
                "categories": [
                  {
                    "color": "#f3c32c",
                    "name": "Housing",
                    "score_out_of_10": 5.710999999999999
                  },
                  {
                    "color": "#f3d630",
                    "name": "Cost of Living",
                    "score_out_of_10": 3.343
                  },.....

The code.  I use React, Redux and Lodash and I tried to iterate the data by map function.

 let item;
   if(this.props.data) {
          item = _.map(this.props.data._embedded.city:search-results._embedded.city:item._embedded.city:urban_area._embedded.ua:scores.categories,
    /** This nested props doesn't work **/
    data => {
    return (

{data.name}

{data.score_out_of_10}

         )
     })

Is there a better way to iterate the data in heavily nested JSON data?

Body:
Since you mentioned lodash try to use the get utility :

import _get from 'lodash/get';

    _get(this.props.data, '_embedded.city:search-results._embedded.city:item._embedded.city:urban_area._embedded.ua:scores.categories', ''),

To prevent the use of the reserved keyword : when you try to access the data, and this helps also to prevent the app from crashing when the data don't exist.


问:
Where is the datewidget in my wagtail formbuilder?
I am implementing an AbstractEmailForm using wagtail form builder. The date-widget is not showing in the date-field. Is this a current bug? Or am I missing something?</p>

答:
Wagtail doesn't provide a date chooser widget for forms rendered on your site front-end, as that would involve inserting custom Javascript onto your template - something that Wagtail makes a point of not doing (since the contents of the template should always be under your control).

You're free to install your own preferred date chooser component, such as the jQuery UI datepicker, and apply it to the form field with a line of code such as:

```<code>$('input#id_date').datepicker()
</code>```

Body:
Wagtail doesn't provide a date chooser widget for forms rendered on your site front-end, as that would involve inserting custom Javascript onto your template - something that Wagtail makes a point of not doing (since the contents of the template should always be under your control).

You're free to install your own preferred date chooser component, such as the jQuery UI datepicker, and apply it to the form field with a line of code such as:

$('input#id_date').datepicker()


问:
How to get member type of boost::mpl placeholders during fold
Say there are two classes:

```<code>struct A
{
    using Key = int;
    using Value = char;
};

struct B
{
    using Key = char;
    using Value = float;
};
</code>```

I want to use their member types to define the Fusion map:

```<code>typedef boost::fusion::map
<
    boost::fusion::pair< int , char > ,
    boost::fusion::pair< char , float >
> desired_type;
</code>```

So I decided to use MPL fold to obtain the type:

```<code>typedef boost::fusion::result_of::as_map< boost::mpl::fold
<
    boost::mpl::vector< A , B > ,

    boost::fusion::map< > ,

    boost::fusion::result_of::push_back
    <
        boost::mpl::_1 ,
        boost::fusion::result_of::make_pair
        <
            boost::mpl::_2 ::Key , boost::mpl::_2 ::Value
        >
    >
>::type >::type map_type;
</code>```

But of course that couldn't work, as boost::mpl::_N are really metafunctions returning the Nth argument.

So, I defined two auxiliary metafunctions:

```<code>template< class T >
struct GetInnerKey
{
    typedef typename T::Key type;
};

template< class T >
struct GetInnerValue
{
    typedef typename T::Value type;
};
</code>```

and defined the fold properly:

```<code>typedef boost::fusion::result_of::as_map< boost::mpl::fold
<
    boost::mpl::vector< A , B > ,

    boost::fusion::map< > ,

    boost::fusion::result_of::push_back
    <
        boost::mpl::_1 ,
        boost::fusion::result_of::make_pair
        <
            GetInnerKey< boost::mpl::_2 > , GetInnerValue< boost::mpl::_2 >
        >
    >
>::type >::type map_type;
</code>```

(Live at Coliru)

My questions are:

Is there a way to get rid of GetInnerKey< > and GetInnerValue< > using something already defined in MPL or Fusion?

Is there a way to avoid using boost::fusion::result_of::as_map< >?

Is this the right approach to accomplish my intent?

答:
Place holders are meta-functions and should be used with lazy evaluation. The ::types inside placeholders _1 & _2 are some complex types before evaluation (You could check them by typeof (with g++)).

As class A & B are not meta functions, so probably you have to write meta functions to handle interactions with class A & B.

e.g.

```<code>template <class PT1, class... PTs>
struct map_type
{
    typedef typename map_type<PTs...>::type pts_map;
    typedef typename boost::fusion::result_of::as_map<
        boost::fusion::joint_view<
            boost::fusion::map<
                boost::fusion::pair< typename PT1::Key, typename PT1::Value>
            >,
            pts_map
        >
    >::type type;
};

template <class PT1>
struct map_type<PT1>
{
    typedef boost::fusion::map<
        boost::fusion::pair< typename PT1::Key, typename PT1::Value>
    > type;
};
</code>```

Live on Coliru

Body:
Say there are two classes:

struct A
{
    using Key = int;
    using Value = char;
};

struct B
{
    using Key = char;
    using Value = float;
};

I want to use their member types to define the Fusion map:

typedef boost::fusion::map
<
    boost::fusion::pair< int , char > ,
    boost::fusion::pair< char , float >
> desired_type;

So I decided to use MPL fold to obtain the type:

typedef boost::fusion::result_of::as_map< boost::mpl::fold
<
    boost::mpl::vector ,

    boost::fusion::map< > ,

    boost::fusion::result_of::push_back
    <
        boost::mpl::_1 ,
        boost::fusion::result_of::make_pair
        <
            boost::mpl::_2 ::Key , boost::mpl::_2 ::Value
        >
    >
>::type >::type map_type;

But of course that couldn't work, as boost::mpl::_N are really metafunctions returning the Nth argument.

So, I defined two auxiliary metafunctions:

template< class T >
struct GetInnerKey
{
    typedef typename T::Key type;
};

template< class T >
struct GetInnerValue
{
    typedef typename T::Value type;
};

and defined the fold properly:

typedef boost::fusion::result_of::as_map< boost::mpl::fold
<
    boost::mpl::vector ,

    boost::fusion::map< > ,

    boost::fusion::result_of::push_back
    <
        boost::mpl::_1 ,
        boost::fusion::result_of::make_pair
        <
            GetInnerKey< boost::mpl::_2 > , GetInnerValue< boost::mpl::_2 >
        >
    >
>::type >::type map_type;

(Live at Coliru)

My questions are:

Is there a way to get rid of GetInnerKey< > and GetInnerValue< > using something already defined in MPL or Fusion?

Is there a way to avoid using boost::fusion::result_of::as_map< >?

Is this the right approach to accomplish my intent?

Body:
Place holders are meta-functions and should be used with lazy evaluation. The ::types inside placeholders _1 & _2 are some complex types before evaluation (You could check them by typeof (with g++)).

As class A & B are not meta functions, so probably you have to write meta functions to handle interactions with class A & B.

e.g.

template <class PT1, class... PTs>
struct map_type
{
    typedef typename map_type<PTs...>::type pts_map;
    typedef typename boost::fusion::result_of::as_map<
        boost::fusion::joint_view<
            boost::fusion::map<
                boost::fusion::pair< typename PT1::Key, typename PT1::Value>
            >,
            pts_map
        >
    >::type type;
};

template <class PT1>
struct map_type<PT1>
{
    typedef boost::fusion::map<
        boost::fusion::pair< typename PT1::Key, typename PT1::Value>
    > type;
};

Live on Coliru


问:
B+Tree on-disk implementation in Java
Does anyone know where to find a B+Tree on-disk implementation? I went through google forward and backward and unfortunately I couldn't find anything sensible. Other threads have suggested to maybe take the tree from sqlite, sqljet or bdb but these trees are nested in the whole database and you can't really "just" filter out the B+Tree.
I'm really looking for only a on-disk B+Tree... without any fancy things around.</p>

答:
I've implemented disk-based B+-tree in the past.
https://github.com/myui/xbird/blob/master/xbird-open/main/src/java/xbird/storage/index/BIndexFile.java

Find usage in https://github.com/myui/xbird/blob/master/xbird-open/main/test/java/xbird/storage/index/BIndexMultiValueFileTest.java

Title: B+Tree on-disk implementation in Java