class RowModeQueryOperationsBase extends AbstractQueryOperations {
    public RowModeQueryOperationsBase(String thingType,
                                      String thingTemplateId,
                                      String thingId,
                                      MetricBuilder metricBuilder,
                                      DataSettings settings,
                                      ThingsRegistry registry) {
        super(thingType, thingTemplateId, thingId, metricBuilder, settings, registry);
    }

    @Override
    protected final Flux<ThingPropertyDetail> queryProperty(@Nonnull QueryParamEntity param,
                                                            @Nonnull ThingMetadata metadata,
                                                            @Nonnull Map<String, PropertyMetadata> properties) {
        String metric = metricBuilder.createPropertyMetric(thingType, thingTemplateId, thingId);
        Query<?, QueryParamEntity> query = param.toNestQuery(q -> {
            applyQuery(q);
            // property in ('a','b','c')
            q.in(ThingsDataConstants.COLUMN_PROPERTY_ID, properties.keySet());
        });

        return this
            .doQuery(metric, query)
            .mapNotNull(data -> this
                .applyProperty(
                    ThingPropertyDetail
                        .of(data, properties.get(data.getString(ThingsDataConstants.COLUMN_PROPERTY_ID, null))),
                    data.getData()))
            ;
    }

    protected Flux<ThingPropertyDetail> queryEachProperty(@Nonnull String metric,
                                                          @Nonnull Query<?, QueryParamEntity> query,
                                                          @Nonnull ThingMetadata metadata,
                                                          @Nonnull Map<String, PropertyMetadata> properties) {
        return Flux
            .fromIterable(properties.entrySet())
            .flatMap(e -> this
                         .doQuery(metric, query
                             .getParam()
                             .clone()
                             .toQuery()
                             .and(ThingsDataConstants.COLUMN_PROPERTY_ID, e.getKey()))
                         .mapNotNull(data -> this
                             .applyProperty(
                                 ThingPropertyDetail
                                     .of(data, properties.get(data.getString(ThingsDataConstants.COLUMN_PROPERTY_ID, null))),
                                 data.getData())),
                     16);
    }

    protected ThingPropertyDetail applyProperty(ThingPropertyDetail detail, Map<String, Object> data) {<FILL_FUNCTION_BODY>}

    @Override
    protected final Mono<PagerResult<ThingPropertyDetail>> queryPropertyPage(@Nonnull QueryParamEntity param,
                                                                             @Nonnull ThingMetadata metadata,
                                                                             @Nonnull Map<String, PropertyMetadata> properties) {
        String metric = metricBuilder.createPropertyMetric(thingType, thingTemplateId, thingId);
        Query<?, QueryParamEntity> query = param.toNestQuery(q -> {
            applyQuery(q);
            // property in ('a','b','c')
            q.in(ThingsDataConstants.COLUMN_PROPERTY_ID, properties.keySet());
        });

        return this
            .doQueryPage(metric,
                         query,
                         data -> this
                             .applyProperty(
                                 ThingPropertyDetail
                                     .of(data, properties.get(data.getString(ThingsDataConstants.COLUMN_PROPERTY_ID, null))),
                                 data.getData()));
    }

    @Override
    protected abstract Flux<TimeSeriesData> doQuery(String metric, Query<?, QueryParamEntity> query);

    @Override
    protected abstract <T> Mono<PagerResult<T>> doQueryPage(String metric,
                                                            Query<?, QueryParamEntity> query,
                                                            Function<TimeSeriesData, T> mapper);

    @Override
    protected abstract Flux<AggregationData> doAggregation(String metric, AggregationRequest request, AggregationContext context);
}

        if (detail == null) {
            return null;
        }
        if (detail.getThingId() == null) {
            detail.thingId((String) data.get(metricBuilder.getThingIdProperty()));
        }
        return detail;
    
<methods>public non-sealed void <init>() ,public final transient Flux<org.jetlinks.community.timeseries.query.AggregationData> aggregationProperties(org.jetlinks.community.things.data.AggregationRequest, org.jetlinks.community.things.data.PropertyAggregation[]) ,public final transient Flux<org.jetlinks.community.things.data.ThingPropertyDetail> queryEachProperty(QueryParamEntity, java.lang.String[]) ,public final Flux<org.jetlinks.community.things.data.ThingEvent> queryEvent(java.lang.String, QueryParamEntity, boolean) ,public Mono<PagerResult<org.jetlinks.community.things.data.ThingEvent>> queryEventPage(java.lang.String, QueryParamEntity, boolean) ,public Flux<org.jetlinks.community.things.data.ThingMessageLog> queryMessageLog(QueryParamEntity) ,public Mono<PagerResult<org.jetlinks.community.things.data.ThingMessageLog>> queryMessageLogPage(QueryParamEntity) ,public final transient Flux<org.jetlinks.community.things.data.ThingPropertyDetail> queryProperty(QueryParamEntity, java.lang.String[]) ,public final transient Mono<PagerResult<org.jetlinks.community.things.data.ThingPropertyDetail>> queryPropertyPage(QueryParamEntity, java.lang.String[]) <variables>protected final non-sealed org.jetlinks.community.things.data.operations.MetricBuilder metricBuilder,protected final non-sealed org.jetlinks.core.things.ThingsRegistry registry,protected final non-sealed org.jetlinks.community.things.data.operations.DataSettings settings,protected final non-sealed java.lang.String thingId,protected final non-sealed java.lang.String thingTemplateId,protected final non-sealed java.lang.String thingType