Skip to content

Commit

Permalink
✨ Introducing beta distinct query
Browse files Browse the repository at this point in the history
  • Loading branch information
Romitou committed Aug 18, 2021
1 parent d5c15fd commit c89f28b
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 6 deletions.
48 changes: 48 additions & 0 deletions src/main/java/fr/romitou/mongosk/adapters/MongoDeserializers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package fr.romitou.mongosk.adapters;

import org.bson.BsonValue;

import java.util.Arrays;

public class MongoDeserializers {

public static Object[] deserializeBsonValues(BsonValue[] values) {
return Arrays.stream(values).map(MongoDeserializers::deserializeBsonValue).toArray();
}

public static Object deserializeBsonValue(BsonValue value) {
switch (value.getBsonType()) {
case ARRAY:
return value.asArray().toArray();
case INT32:
return value.asInt32().getValue();
case INT64:
return value.asInt64().getValue();
case BINARY:
return value.asBinary().getData();
case DOUBLE:
return value.asDouble().getValue();
case STRING:
return value.asString().getValue();
case SYMBOL:
return value.asSymbol().getSymbol();
case BOOLEAN:
return value.asBoolean().getValue();
case DOCUMENT:
return MongoSKAdapter.deserializeValue(MongoSKAdapter.bsonDocumentToDocument(value.asDocument()));
case DATE_TIME:
return value.asDateTime().getValue();
case TIMESTAMP:
return value.asTimestamp().getValue();
case OBJECT_ID:
return value.asObjectId().getValue();
case DECIMAL128:
return value.asDecimal128().intValue();
case REGULAR_EXPRESSION:
return value.asRegularExpression().getPattern();
default:
return null;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package fr.romitou.mongosk.skript.expressions;

import ch.njol.skript.Skript;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.Since;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.ExpressionType;
import ch.njol.skript.lang.SkriptParser;
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.util.Kleenean;
import com.mongodb.reactivestreams.client.DistinctPublisher;
import fr.romitou.mongosk.Logger;
import fr.romitou.mongosk.SubscriberHelpers;
import fr.romitou.mongosk.adapters.MongoDeserializers;
import fr.romitou.mongosk.elements.MongoSKCollection;
import fr.romitou.mongosk.elements.MongoSKDocument;
import fr.romitou.mongosk.elements.MongoSKFilter;
import org.bson.BsonValue;
import org.bukkit.event.Event;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;

@Name("Mongo distinct query (BETA)")
@Description("The distinct query is useful when you want to retrieve a specific field from each document in a given " +
"collection. For example, if you have documents with a \"name\" field, you can use this expression to retrieve " +
"all the \"name\" fields of the documents in the collection. Useful, isn't it?" +
"" +
"This expression does not accept constructed queries because there is no need to use it. " +
"They can only be used with the find query.")
@Examples({"set {_names::*} to all mongo fields distincted by \"name\" of collection {myCollection}",
"",
"set {_filter} to mongosk filter where field \"admin\" is true",
"set {_adminNames::*} to all mongo fields distincted by \"name\" with filter {_filter} of collection {myCollection}"})
@Since("2.2.1")
public class ExprMongoDisctinctResult extends SimpleExpression<Object> {

static {
Skript.registerExpression(
ExprMongoDisctinctResult.class,
Object.class,
ExpressionType.COMBINED,
"(1¦first|2¦all) mongo[(sk|db)] field[s] distincted by [field] %string% [(with|by) [filter] %-mongoskfilter%] (of|from) collection %mongoskcollection%"
);
}

private Expression<String> exprDistinctedBy;
private Expression<MongoSKFilter> exprMongoSKFilter;
private Expression<MongoSKCollection> exprMongoSKCollection;
private Boolean isFirstDocument;

@SuppressWarnings("unchecked")
@Override
public boolean init(@Nonnull Expression<?>[] exprs, int matchedPattern, @Nonnull Kleenean isDelayed, @Nonnull SkriptParser.ParseResult parseResult) {
exprDistinctedBy = (Expression<String>) exprs[0];
exprMongoSKFilter = (Expression<MongoSKFilter>) exprs[1];
exprMongoSKCollection = (Expression<MongoSKCollection>) exprs[2];
isFirstDocument = parseResult.mark == 1;
return true;
}

@Override
protected Object[] get(@Nonnull final Event e) {

String distinctedBy = exprDistinctedBy.getSingle(e);
MongoSKCollection mongoSKCollection = exprMongoSKCollection.getSingle(e);

if (distinctedBy == null || mongoSKCollection == null)
return new Object[0];

DistinctPublisher<BsonValue> distinctPublisher = mongoSKCollection.getMongoCollection().distinct(distinctedBy, BsonValue.class);
if (exprMongoSKFilter != null) {
MongoSKFilter filter = exprMongoSKFilter.getSingle(e);
if (filter != null) {
distinctPublisher.filter(filter.getFilter());
}
}

long distinctQuery = System.currentTimeMillis();
SubscriberHelpers.ObservableSubscriber<BsonValue> observableSubscriber = new SubscriberHelpers.OperationSubscriber<>();
if (isFirstDocument)
distinctPublisher.first().subscribe(observableSubscriber);
else
distinctPublisher.subscribe(observableSubscriber);
List<BsonValue> values = observableSubscriber.get();
Logger.debug("Simple distinct query executed in " + (System.currentTimeMillis() - distinctQuery) + "ms.");

return MongoDeserializers.deserializeBsonValues(values.toArray(new BsonValue[0]));
}

@Override
public boolean isSingle() {
return isFirstDocument;
}

@Override
@Nonnull
public Class<? extends MongoSKDocument> getReturnType() {
return MongoSKDocument.class;
}

@Override
@Nonnull
public String toString(@Nullable final Event e, final boolean debug) {
return (isFirstDocument ? "first mongosk document" : "all mongosk documents") + " distincted by field " + exprDistinctedBy.toString(e, debug) + (exprMongoSKFilter == null ? "" : "with filter " + exprMongoSKFilter.toString(e, debug)) + " of collection " + exprMongoSKCollection.toString(e, debug);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
import javax.annotation.Nullable;
import java.util.List;

@Name("Mongo query result")
@Description("Use this expression if you want to make simple requests, easily and quickly. " +
@Name("Mongo find query")
@Description("Use this expression if you want to make simple find requests, easily and quickly. " +
"To do so, you must specify the type of your query: are you looking for several documents or the first document in " +
"the collection? Then, the first means is to use a filter to specify the type of data you are looking for. " +
"Finally, you need to specify where the query should ask for the data, i.e. in which collection." +
Expand All @@ -48,15 +48,15 @@
"set mongo filter of {_query} to {myfilter}",
"set {_doc} to first mongo document of query {_query}"})
@Since("2.0.0")
public class ExprMongoQueryResult extends SimpleExpression<MongoSKDocument> {
public class ExprMongoFindResult extends SimpleExpression<MongoSKDocument> {

static {
Skript.registerExpression(
ExprMongoQueryResult.class,
ExprMongoFindResult.class,
MongoSKDocument.class,
ExpressionType.COMBINED,
"(1¦first|2¦all) mongo[(sk|db)] document[s] [(with|by) [filter] %-mongoskfilter%] (of|from) collection %mongoskcollection%",
"(1¦first|2¦all) mongo[(sk|db)] document[s] (of|from) query %mongoskquery%"
"[find] (1¦first|2¦all) mongo[(sk|db)] document[s] [(with|by) [filter] %-mongoskfilter%] (of|from) collection %mongoskcollection%",
"[find] (1¦first|2¦all) mongo[(sk|db)] document[s] (of|from) query %mongoskquery%"
);
}

Expand Down

0 comments on commit c89f28b

Please sign in to comment.