如何在Ionic的Firebase查询中添加条件?

时间:2019-05-21 08:36:28

标签: angular typescript firebase ionic-framework google-cloud-firestore

我正在开发一个基于位置的应用程序,这是一个大学项目的一部分,该项目中,用户应该能够“将某些消息放入hin周围,以供其他用户查看。我正在使用Ionic v4和Firebase作为我的数据库。不幸的是,我对Ionic和Firebase还是很陌生,所以如果我在这里找不到问题的答案,我真的不知道该怎么办,所以我想我也可以问问。

更多背景知识:我得到了用户可以写的 drops ,现在我希望其他用户能够对这些 drops 进行投票和降级。在带有leaflet的openstreetmap中可以看到 drops 。到目前为止,我已经可以按预期进行所有操作,但是现在我想根据该得分获得所有 drop 的前20%,并更改地图上显示的图标。我想我可以通过在原始数据库中添加另一个数据库查询来实现这一目标,该查询仅从数据库中获取每个 drop 。我用ionic service拉数据库条目。

这是我获取所有条目的原始查询:

private dropsCollection: AngularFirestoreCollection<Drop>;
private drops: Observable<Drop[]>;

this.dropsCollection = db.collection('drops', ref =>
    ref.where('createdAt', '>=', validMinTime)
);

这是获取 kingDrops 的查询:

private kingdropsCollection: AngularFirestoreCollection<Drop>;
private kingDrops: Observable<Drop[]>;

// 2 should be replaced dynamicly with the total amount of drops*0.2
const topDrops = 2; 

this.kingdropsCollection = db.collection('drops', ref =>
    ref.orderBy('score', 'desc').limit(topDrops)
);

据我所知语法应该没问题,但是如何在前端中将此查询作为“条件”实现?我需要能够动态确定我的 drops 中的哪一个是 kingDrop 并相应地更改图标。这是我的 home.page.ts

的代码
import {Component, ElementRef, ViewChild} from '@angular/core';
import * as Geolib from 'geolib';

import leaflet from 'leaflet';
import {NavController} from '@ionic/angular';
import {Drop, DropService} from '../../services/drop.service';
import {AppComponent} from '../../app.component';
import {Router} from '@angular/router';
import {UserService} from '../../services/user.service';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss']
})
export class HomePage {

    myDrops: Drop[];

    @ViewChild('map') mapContainer: ElementRef;

    map: any;

    constructor(
        private router: Router,
        public navCtrl: NavController,
        public dropService: DropService,
        public appComponent: AppComponent,
        public userService: UserService
    ) {}
    ionViewDidEnter() {
        this.loadmap();
    }
    loadmap() {
        const positionIcon = leaflet.icon({
            iconUrl: '../../../assets/icon/position.png',
            shadowUrl: '../../../assets/icon/position-shadow.svg',

            iconSize: [30, 30], // size of the icon
            shadowSize: [30, 30], // size of the shadow
            iconAnchor: [0, 0], // point of the icon which will correspond to marker's location
            shadowAnchor: [2, -2], // the same for the shadow
            popupAnchor: [0, 0] // point from which the popup should open relative to the iconAnchor
        });
        this.map = leaflet.map('map').fitWorld();
        leaflet.tileLayer(
            'https://api.maptiler.com/maps/positron/{z}/{x}/{y}.png?key=JrASdfPCkNw3CYBKAD6E',
            {
            attributions:
            'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>',
            maxZoom: 18,
            minZoom: 15
            }
        )
        .addTo(this.map);
        this.map.locate({
            setView: true,
            maxZoom: 10,
            minZoom: 15
        })
        .on('locationfound', e => {
            const markerGroup = leaflet.featureGroup();
            const marker: any = leaflet
            .marker([e.latitude, e.longitude], {
                icon: positionIcon,
                zIndexOffset: -1000 // put the markers on top of the location marker
            })
            .on('click', () => {
                console.log('Position marker clicked');
            });
            markerGroup.addLayer(marker);
            this.map.addLayer(markerGroup);
        })
        .on('locationerror', err => {
            console.log(err.message);
        });
        this.loadMarkers();
    }
    loadMarkers() {
        const greyDropIcon = leaflet.icon({
            iconUrl: '../../../assets/icon/grey-drop.png',
            shadowUrl: '../../../assets/icon/drop-shadow.svg',

            iconSize: [25, 30], // size of the icon
            shadowSize: [25, 30], // size of the shadow
            iconAnchor: [0, 0], // point of the icon which will correspond to marker's location
            shadowAnchor: [2, -2], // the same for the shadow
            popupAnchor: [-3, -5] // point from which the popup should open relative to the iconAnchor
        });

        this.dropService.getDrops().subscribe((drops: any) => {
            drops.forEach(singledrop => {
                if (this.dropService.isDropVisible(singledrop)) {
                    const dropGroup = leaflet.featureGroup();
                    // check visibleDrops array of user for drops and add them
                    const dist = this.checkDropDistance(singledrop);
                    if (dist < 1500 && singledrop.score > -10) {
                        this.setDropVisible(singledrop);
                    } else if (singledrop.score > -10) {
                        const drop: any = leaflet.marker([singledrop.latitude, singledrop.longitude], {
                            icon: greyDropIcon
                        })
                        .on('click', () => {
                            console.log('Marker clicked, but out of range');
                        });
                        dropGroup.addLayer(drop);
                        this.map.addLayer(dropGroup);
                    }
                }
            });
        });
    }
    // ... 
}

我已经尝试实现 kingDrops ,就像上面的 drops 这样:

this.dropService.getKingDrops().subscribe((drops: any) => {
    //..
});

但是它没有成功,因为原始的放置点已经在我的地图上,所以它会被复制。.我需要某种条件来确定 drop 是否是 kingDrop 还是不执行,并相应地实现图标,但是我不知道写这种条件的语法。

有人可以帮我吗?

1 个答案:

答案 0 :(得分:0)

我建议您在“ Drop”模型中添加一个可选的boolean参数,以指示主滴。 由于您的王牌掉落很少,因此您应该遍历每一项并使用方法.data('key')搜索原始数组以找到匹配项 然后,您应该将该数组索引处的drop的可选参数更改为true,然后使用此变量加载图标 示例: