我在mongodb中的集合类似于SQL中的下表:
观点(公司,情绪)
现在,我需要执行这样的查询:
SELECT
Company,
SUM(CASE WHEN Sentiment >0 THEN Sentiment ELSE 0 END) AS SumPosSenti,
SUM(CASE WHEN Sentiment <0 THEN Sentiment ELSE 0 END) AS SumNegSenti
FROM Sentiments
GROUP BY Company
我应该怎么做才能在Mongo中编写此查询?我陷入了以下问题:
db.Sentiments.aggregate(
{ $project: {_id:0, Company:1, Sentiment: 1} },
{ $group: {_id: "$Company", SumPosSenti: {$sum: ? }, SumNegSenti: {$sum: ? } } }
);
答案 0 :(得分:47)
正如Sammaye建议的那样,您需要使用$cond
聚合投影运算符来执行此操作:
db.Sentiments.aggregate(
{ $project: {
_id: 0,
Company: 1,
PosSentiment: {$cond: [{$gt: ['$Sentiment', 0]}, '$Sentiment', 0]},
NegSentiment: {$cond: [{$lt: ['$Sentiment', 0]}, '$Sentiment', 0]}
}},
{ $group: {
_id: "$Company",
SumPosSentiment: {$sum: '$PosSentiment'},
SumNegSentiment: {$sum: '$NegSentiment'}
}});
答案 1 :(得分:28)
从版本3.4开始,我们可以使用$switch
运算符,该运算符允许$group
阶段中的逻辑条件处理。当然,我们仍然需要使用$sum
累加器来返回总和。
db.Sentiments.aggregate(
[
{ "$group": {
"_id": "$Company",
"SumPosSenti": {
"$sum": {
"$switch": {
"branches": [
{
"case": { "$gt": [ "$Sentiment", 0 ] },
"then": "$Sentiment"
}
],
"default": 0
}
}
},
"SumNegSenti": {
"$sum": {
"$switch": {
"branches": [
{
"case": { "$lt": [ "$Sentiment", 0 ] },
"then": "$Sentiment"
}
],
"default": 0
}
}
}
}}
]
)
如果您尚未将mongod
迁移到3.4或更高版本,请注意此$project
中的answer阶段是多余的,因为$cond
运算符会返回一个数字值意味着您可以$group
将文档$sum
应用于$cond
表达式。
这将提高应用程序的性能,尤其是对于大型集合。
db.Sentiments.aggregate(
[
{ '$group': {
'_id': '$Company',
'PosSentiment': {
'$sum': {
'$cond': [
{ '$gt': ['$Sentiment', 0]},
'$Sentiment',
0
]
}
},
'NegSentiment': {
'$sum': {
'$cond': [
{ '$lt': ['$Sentiment', 0]},
'$Sentiment',
0
]
}
}
}}
]
)
考虑一个带有以下文件的集合Sentiments:
{ "Company": "a", "Sentiment" : 2 }
{ "Company": "a", "Sentiment" : 3 }
{ "Company": "a", "Sentiment" : -1 }
{ "Company": "a", "Sentiment" : -5 }
聚合查询产生:
{ "_id" : "a", "SumPosSenti" : 5, "SumNegSenti" : -6 }
答案 2 :(得分:2)
解释上面使用数组语法的片段:
public class WebLinkActivity extends Activity {
WebView mWebView;
private Button mCancel;
private String mUrl;
ProgressDialog progressDialog;
public void clearCookies() {
try {
android.webkit.CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
} catch (Exception ex) {
}
}
public void closeWebLinkClick(View view) {
Utilities.logInfo("closeWebLinkClick", "Close WebLink Full Screen");
setResult(Activity.RESULT_CANCELED, null);
finish();
}
@Override
public void onResume() {
super.onResume();
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setResult(Activity.RESULT_OK, null);
Bundle extras = getIntent().getExtras();
mUrl = extras.getString("url");
// Setup the web view. It will redirect to SSO site for login
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_weblink);
mCancel = (Button) findViewById(R.id.closeWebLink);
mCancel.setTextColor(Color.WHITE);
mWebView = (WebView) findViewById(R.id.weblinkViewer);
progressDialog = new ProgressDialog(WebLinkActivity.this);
progressDialog.setMessage("Loading...");
progressDialog.show();
// Link not provided
if (Utilities.stringIsBlank(mUrl)) {
String dataString = "<head><style type='text/css'>"
+ "body{margin:auto auto;text-align:center;vertical-align: middle;} </style></head>"
+ "<body><img src=\"invalid_link.png\"/></body>";
mWebView.loadDataWithBaseURL("file:///android_res/drawable/", dataString, "text/html", "utf-8", null);
if (progressDialog != null)
progressDialog.dismiss();
}
// Network is not available
else if (!Utilities.isNetworkAvailable()) {
String dataString = "<head><style type='text/css'>"
+ "body{margin:auto auto;text-align:center;vertical-align: middle;} </style></head>"
+ "<body><img src=\"not_connected.png\"/></body>";
mWebView.loadDataWithBaseURL("file:///android_res/drawable/", dataString, "text/html", "utf-8", null);
if (progressDialog != null)
progressDialog.dismiss();
}
// Normal processing
else {
// See if url is missing http. If so add it in
if (!mUrl.toLowerCase().contains("http")) {
mUrl = "http://" + mUrl;
}
// Most likely an image is ends with image attribute
if (Utilities.isImage(mUrl)) {
String html = "<html><body><img src=\"" + mUrl + "\" width=\"100%\"/></body></html>";
mWebView.loadData(html, "text/html", null);
if (progressDialog != null)
progressDialog.dismiss();
}
// Normal web view
else {
mWebView.setWebChromeClient(new WebChromeClient() {
public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
// callback.invoke(String origin, boolean allow, boolean remember);
callback.invoke(origin, true, false);
}
});
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
@Override
public void onPageFinished(WebView view, String url) {
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
});
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setAppCacheEnabled(true);
// HTML5 API flags
mWebView.getSettings().setAppCacheEnabled(true);
mWebView.getSettings().setDatabaseEnabled(true);
mWebView.getSettings().setDomStorageEnabled(true);
mWebView.loadUrl(mUrl);
}
}
}
}
等于:
PosSentiment: {$cond: [{$gt: ['$Sentiment', 0]}, '$Sentiment', 0]}
数组语法将长语法概括为PosSentiment: {$cond: { if: {$gt: ['$Sentiment', 0]}, then: '$Sentiment', else: 0} }