Java tutorial
/* * Copyright 2013 Robert Gacki <robert.gacki@cgi.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.otto.mongodb.profiler.op; import com.mongodb.DBObject; import org.joda.time.DateTime; import java.util.*; import static de.otto.mongodb.profiler.util.MongoSupport.require; /** * An explanation of a query. * * @author Robert Gacki */ public class Explanation { private static DBObject query(final QueryProfile profile) { if (profile.getQuery().containsField("$query")) { return require("$query", DBObject.class, profile.getQuery()); } if (profile.isSnapshot() && profile.getQuery().containsField("query")) { return require("query", DBObject.class, profile.getQuery()); } return profile.getQuery(); } private static Collection<ExplanationIssue> findIssuesInExplanation(final DBObject explanationResult, final QueryProfile profile) { final List<ExplanationIssue> result = new ArrayList<>(1); final String cursor = ((String) explanationResult.get("cursor")); if (cursor != null && !cursor.toLowerCase(Locale.ENGLISH).startsWith("btreecursor ")) { final DBObject query = query(profile); // Does the query simply finds all documents if (query.keySet().isEmpty()) { // If it is a count, it will just ask for the document number without a scan if (profile instanceof CountProfile == false) { result.add(ExplanationIssue.FULL_TABLE_SCAN); } } // ...or is the index missing else { result.add(ExplanationIssue.MISSING_INDEX); } } final Boolean scanAndOrder = ((Boolean) explanationResult.get("scanAndOrder")); if (scanAndOrder != null && scanAndOrder.booleanValue()) { result.add(ExplanationIssue.RESULTS_ORDERED_AFTER_SCAN); } return Collections.unmodifiableList(result); } private final DBObject data; private final DateTime ceatedAt; private final Collection<ExplanationIssue> issues; /** * Creates a new explanation. * * @param data the explanation data * @param profile the profile the explanation was created for * @param ceatedAt the date and time when the explanation was created */ public Explanation(final DBObject data, final QueryProfile profile, final DateTime ceatedAt) { this.data = data; this.ceatedAt = ceatedAt; this.issues = findIssuesInExplanation(data, profile); } /** * Returns the explanation data. * * @return the explanation data */ public DBObject getData() { return data; } /** * Returns the date and time the explanation was created. * * @return the date and time the explanation was created */ public DateTime getCreatedAt() { return ceatedAt; } /** * Returns a collection of issues that were found in this explanation. Returns an empty collection if there are no * issues found. * * @return the collection of issues which may be empty */ public Collection<ExplanationIssue> getIssues() { return issues; } }